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?

1 Answer 1

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");
10
  • 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 9, 2018 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 9, 2018 at 20:05
  • Appendix: (1) The python program can execute gnome-terminal --working-directory='/home/<user>/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); (2) We can use tmux (or screen) instead of a terminal (reference).
    – pa4080
    Apr 9, 2018 at 20:07
  • 1
    @sc241, done, please review the answer.
    – pa4080
    Apr 9, 2018 at 20:53
  • 1
    @sc241, #!/usr/bin/perl is shebang. 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 9, 2018 at 22:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.