3

I have to run terminal codes via os.system() in Python. Two commands should be run in two terminals separately. Is it possible to specify a unique name/ID to the terminal windows to run each command in its specified terminal window?

muru
  • 193,181
  • 53
  • 473
  • 722
sc241
  • 95
  • 1
  • 7

1 Answers1

4

Each terminal you open gets a uniquely numbered file (a pseudoterminal slave (PTS) device to be exact) in /dev/pts/ with whom it can be recognized and addressed. To get the correspondent filename of a terminal window you can use e.g. tty (see this answer for alternatives; read man pts for more):

$ tty
/dev/pts/4

You can use this filename for instance to redirect output to a different terminal window like so:

$ echo test >/dev/pts/4  # run anywhere
test                     # printed in terminal window 4

You can't really run a command in another terminal, simply because it's not the terminal that runs a command, but rather the shell which normally runs in a terminal. You can however emulate the behaviour of a command run in a terminal window with redirections as follows (taken from Linux pseudo-terminals: executing string sent from one terminal in another):

echo test </dev/pts/4 &>/dev/pts/4

If you want to display the command you ran as well I recommand writing a function (How do I use $* while omitting certain input variables like $1 and $2 in bash script?), e.g.:

run_in(){
  t=/dev/pts/$1 &&
  echo "${*:2}" >$t &&
  eval "${@:2}" <$t &>$t
}

In one line:

run_in(){ t=/dev/pts/$1&&echo "${*:2}" >$t&&eval "${@:2}" <$t &>$t;}

Use it like so:

$ run_in 4 echo test  # run anywhere
$ echo test           # printed in terminal window 4 (if prompt was already there)
test                  # printed in terminal window 4

In this scenario the only unknown are the /dev/pts/? numbers that your Python program shall use. One possible way to get these numbers is to launch your own terminal windows, which will output their 'numbers' in to a file, then you can read it [ref]. Let's assume you are using gnome-terminal, the relevant part of the Python code could be something as follow [ref]:

#!/usr/bin/python
import os
import subprocess

os.system("gnome-terminal -x bash -c 'tty > /tmp/my-app-tty-1; exec bash'")
my_terminal_1 = subprocess.Popen(["cat", "/tmp/my-app-tty-1"], stdout=subprocess.PIPE).communicate()[0]
command = "echo Test on: $(date) >" + my_terminal_1
print my_terminal_1
print command
os.system(command)

If it is a Perl script [ref]

#!/usr/bin/perl
os.system("gnome-terminal -x bash -c 'tty > /tmp/my-app-tty-1; exec bash'");
my $my_terminal_1 = `cat /tmp/my-app-tty-1`;
my $command = "echo Test on: \$\(date\) > $my_terminal_1";
print ("$my_terminal_1");
print ("$command");
os.system("$command");
pa4080
  • 29,351
  • 10
  • 85
  • 161
dessert
  • 39,392
  • 12
  • 115
  • 163
  • Thanks for your help, Itried to run this command `os.system("echo "+stopDBCommand+" >/dev/pts/20")` in which `stopDBCommand=/home/esarah/workspace/vt -stop /home/esara/workspace/home/mydb` , it prints the command on terminal, but not running it, i should press enter to run it. It is not running the command, but it randomly ran the command once. how to solve this? – sc241 Apr 09 '18 at 20:02
  • @sc241 Did you read my whole post yet? I explained this and provided a solution in the second part of my answer… – dessert Apr 09 '18 at 20:05
  • Appendix: (1) The python program can execute `gnome-terminal --working-directory='/home//project' -x bash -c "tty > /tmp/my-app-tty-1; exec bash"` to open a new terminal... then we can read the file `/tmp/my-app-tty-1` to get the `pts` number ([reference](https://askubuntu.com/a/967720/566421)); (2) We can use `tmux` (or `screen`) instead of a terminal ([reference](https://askubuntu.com/a/962820/566421)). – pa4080 Apr 09 '18 at 20:07
  • @pa4080 I am very new in terminal command , it is very difficult to understand it. Could you please write an answer? – sc241 Apr 09 '18 at 20:26
  • dessert, thanks for help, where should I write `run_in()` function? I am very new in ubuntu and terminal commands – sc241 Apr 09 '18 at 20:27
  • @pa4080 I would really appreciate it if you could write it here – sc241 Apr 09 '18 at 20:29
  • 1
    @sc241, done, please review the answer. – pa4080 Apr 09 '18 at 20:53
  • @pa4080 what is `#!/usr/bin/perl`? where should I write this codes? Or I do not understand where should i write `run_in` function. could you please explain it? – sc241 Apr 09 '18 at 21:11
  • 1
    @sc241, `#!/usr/bin/perl` is [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)). The code that I added is a working example of a Perl script (sorry for the ugly example, this is my first attempt with Perl). Place the lines in to a file (let's call it `file.pl`), make it executable (`chmod +x file.pl`), and execute it (`./file.pl`) to see the result. `run_in()` is a bash function, you can place it in your `~/.bashrc` file, then execute `source ~/.bashrc` and it will be accessible as shell command. Better idea is to create your own Perl function on its base. – pa4080 Apr 09 '18 at 22:15
  • @pa4080 Thanks for your help, I added the `run_in()` function to `~/.bashrc`, however, once I am sending the command `os.system("run_in 2 "+queryCommand)`, where the `queryCommand=./vt -query ./home/mydb ./home/images/image-001-053.png 2>&1 | tee ./ results.txt` . I am getting this error `sh: 1: run_in: not found`, am I doing mistakes? – sc241 Apr 13 '18 at 19:24