3

I have several terminal windows already open; I just made a change to ~/.bashrc, and I'd like to run source ~/.bashrc in each of the open terminals.

It seems to me that if I just

source ~/.bashrc | tee /dev/pts/{0..12}

, then ~/.bashrc should be run in each terminal. It looks like it was, since I include a clear at the end of ~/.bashrc.

However, what I'm specifically testing is whether

PROMPT_COMMAND="history -a; history -c; history -r; ${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}"

actually creates a single source of truth for all my terminals, and was modified in each open terminal.

Now I'm not sure if this has something to do with writing to /dev/pts/{0..12} or is related to the way that history functions. If I look at one of my open terminals which is running git log, and echo $PROMPT_COMMAND, I do NOT see the modifications I would expect had ~/.bashrc been sourced. As a consequence of the history commands missing, I do not see git log output in a separate terminal, running tail -f ~/.bash_history, which I would expect to see if PROMPT_COMMAND was indeed modified after source ~/.bashrc.

However, if I ask each terminal echo $PROMPT_COMMAND | tee /dev/pts/{0..12}, what the value of PROMPT_COMMAND is, I get:

history -a; history -c; history -r; pre_prompt_command; echo -ne "\033]0;${USER}@${HOSTNAME%%.*}:${PWD/#$HOME/\~}\007"

which includes history -a; history -c; history -r;, the changes that I added in ~/.bashrc.

Now I'm confused. What am I doing wrong? Or what do I not understand correctly? Was PROMPT_COMMAND modified or was it not? Or is this a consequence of how bash / linux works? I'm pretty sure it's user error, and not a bug.

1
  • @Jeff Schaller thank you for the edits Apr 29 at 8:41

1 Answer 1

5

source ~/.bashrc makes the current shell source ~/.bashrc. Redirecting output to tee (that in your case sends it to several /dev/pts/… files) is, well, redirecting output from commands in .bashrc, not the content of .bashrc.

But even if you did cat ~/.bashrc | tee /dev/pts/{0..12}, you would not send the content to the other shells; and with echo 'source ~/.bashrc' | tee /dev/pts/{0..12} you would not inject source ~/.bashrc into the command lines of the other shells. See Construct a command by putting a string into a tty, especially this answer:

A terminal doubles as two things: an input device (such as a keyboard) and a display device (such as a monitor). When you read from the terminal, you get what comes from the input device. When you write to the terminal, the data goes onto the display device.

By sending bytes to /dev/pts/… you can only get reaction from the display device, not from the (nor any) shell that uses it. The display device usually reacts by showing/printing what you sent. Some sequences of bytes are special though.

It so happens clear works by outputting a certain special sequence of bytes, so when you redirected and forked the output, the other terminals reacted by clearing their screens. In general another terminal may or may not react to a "foreign" clear, as the sequence from clear depends on $TERM seen by clear (example), so it's tailored to the terminal you run clear in.

Similarly echo $PROMPT_COMMAND | tee /dev/pts/{0..12} did nothing to the other shells. Your current shell expanded $PROMPT_COMMAND (that should have been double-quoted), echo sent the result to tee, tee sent it to multiple terminals. Each terminal printed the value of the variable provided by the current shell; no other shell was involved.

In general in Linux there is no easy (i.e. as easy as >/dev/pts/… or tee /dev/pts/…) way to inject some string as if you typed it. A programmer can use TIOCSTI. Terminal multiplexers and terminal emulators may provide ways to send keystrokes to terminals they emulate (e.g. send-keys of tmux). Still, even then injecting commands is not an elegant way in general, because the "shell" there may be something other than bash, or it (bash or not) may be busy executing something else that may consume the input and possibly react by doing something you don't want.

Additionally, source ~/.bashrcEnter even straightforwardly typed into the command line of interactive bash may "misbehave". ~/.bashrc is meant to be sourced in a clean shell, once, automatically. Sourcing a new version of it in an old shell is not equivalent to starting a new shell.

1
  • ok I see; So there is no known way to source ~/.bashrc in all open terminals so as to apply changes made to all running terminals? I can ask another SO question if that's more appropriate. Apr 30 at 20:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .