3

Is it possible to run a command in another opened terminal? I know I can redirect the output of a command in another terminal. For example:

ls >/dev/pts/x

Where x can be obtained by running tty on the target terminal. But the command is executed on the current terminal. That is not what I want.

To clarify my real objective, I want to send a command to every opened terminal, to change color theme without having to re-open every terminal.

Chris Davies
  • 116,213
  • 16
  • 160
  • 287
dblouis
  • 199
  • 1
    Did you e.g try cat > /dev/pts/x <<EOF\n $(ls -l)\n EOF ? Where $(ls -l) is in a new line? – Valentin Bajrami Oct 28 '18 at 09:12
  • The command is still executed on the local terminal. I tried with tty instead of ls and it printed the number of the local terminal. – dblouis Oct 28 '18 at 09:17
  • 3
    This feels like an XY problem. What are you trying to achieve by running a command in a different terminal window? – Chris Davies Oct 28 '18 at 09:18
  • 1
    I want to send a command to every opened terminal, to change color theme without having to re-open every terminal. I may have found a solution by sending an IOCTL to the pts. – dblouis Oct 28 '18 at 09:21
  • I wonder what ioctl you're using to change the color of the terminal ;-) –  Oct 28 '18 at 10:24
  • 2
    How do you currently change the color theme of one terminal (the one you're typing to)? – egmont Oct 28 '18 at 10:28
  • 1
    There's an ioctl to synthesize input. So you can implement "typing" simultaneously. But if any of your terminals are somewhere else than at the shell prompt (e.g. in an interactive app like "mutt" where single keystokes can delete emails or such), you'll pretty soon shoot yourself in the foot. – egmont Oct 28 '18 at 10:35
  • @egmont yes, TIOCSTI. But that's still an interesting problem (both the one from the question, and the one from the comments). –  Oct 28 '18 at 11:00
  • TIOCSTI works but it needs root permission so this is not a solution for me. There is a simpler solution but it is not quite what I want: I just modified my prompt command so that it update the color theme every time I press enter – dblouis Oct 28 '18 at 11:04
  • 2
    How do you update the color theme? Let's say the command foo updates it for you, by emitting relevant escape sequences. Then foo > /dev/pts/x should work for updating them in another terminal. (The prompt solution might also be a good one.) – egmont Oct 28 '18 at 11:12
  • you can send color/cursor escapes to a terminal by simply writing to /dev/pts/N or /dev/ttyN; for instance, if /dev/pts/5 is an xterm, you can set its background to red from anywhere with printf %b '\e]11;#ff0000\a' > /dev/pts/5 (of course, you need write permissions to /dev/pts/5). –  Oct 28 '18 at 12:16
  • I still need to know if there is nothing running inside of it because of what @egmont said – dblouis Oct 28 '18 at 12:23
  • It still works with a pretty decent chance if there's an app running inside. (There's a slim, almost negligible chance of your printf cutting in the middle another escape sequence that the app running over there is just printing.) – egmont Oct 28 '18 at 12:36
  • @DBLouis writing to a terminal eg. with printf f > /dev/tty2 won't send f to the program running inside it. And the printf won't cut in the middle of another sequence unless that sequence was already split, ie the app used two write(2)s to put it out. –  Oct 28 '18 at 13:00
  • 1
    @mosvy I said "slim" chance. An app probably doesn't directly split an escape sequence – or a multibyte UTF-8 character, that's also a failure possibility – in two write(2) calls, but might be using a higher level library (print to stdout and the buffer gets filled up), or some layers of software like tmux or ssh might happen to break the flow there. The probability is extremely small, but is there. – egmont Oct 28 '18 at 13:47
  • I am going to write an answer just give me some time :) – dblouis Oct 29 '18 at 11:21
  • @muru ttyecho does not run a command in another tty, it just fakes input with TIOCSTI (which is quite dangerous). Whwn I get time, I will expand my ptrace/gdb hack into something more robust, no matter if this question is closed or not. –  Oct 29 '18 at 12:19
  • @mosvy if it's incorrect, then you should correct it or post a correct answer. But that's quite independent of this question being closed as a duplicate. – muru Oct 29 '18 at 12:23
  • 1
    @muru: I disagree that this question is a duplicate of the one you cited, because this question is unclear. It appears to be an XY question where the OP doesn’t know what they want. DBLouis says (paraphrased) my real objective is to change color theme every opened terminal, but doesn’t demonstrate a clear understanding of what that means or how it would be approached. ISTM that they are really want to know how to write ANSI escape sequences to another terminal, not how to run a command on another terminal. Also, they have said “TIOCSTI … needs root permission so this is not a solution for me.” – G-Man Says 'Reinstate Monica' Oct 29 '18 at 17:01
  • DBLouis: If you had the ability to execute a command in another already opened terminal, what command would you execute (given that your objective is to change the color theme in the other terminal)?  Have you “found a solution by sending an ioctl to the pts”?  You said “I am going to write an answer”; do you have an answer?  Are willing to tell us what it is? – G-Man Says 'Reinstate Monica' Oct 29 '18 at 22:13
  • I have an alternate solution, can someone unlock the question please – dblouis Nov 01 '18 at 08:17

1 Answers1

1

You can send color/cursor escapes to a terminal by simply writing to /dev/pts/N or /dev/ttyN; for instance, if /dev/pts/5 is an xterm, you can set its background to red from anywhere with printf %b '\e]11;#ff0000\a' > /dev/pts/5 (of course, you need write permissions to /dev/pts/5).

There is a slim chance that running such a command may badly interract with other escapes sent by the program(s) running in the terminal, but in the worst case this will only result in a scrambled terminal.

For the more general problem of running a program in another terminal/session, the only way I can think that possible is by hijacking a process running in that terminal, and fork+exec the program from inside it. Example:

gdb -p PID -batch -ex 'p system("ls")'

This gets a lot more involved if the program has to read from the terminal; before the exec, the process will have to be added to the foreground process group.