The 'Wall' command for pseudo terminals over ssh
Quite some time ago, all terminals were physical devices attached to the machine. Today terminals are usually pseudo terminals, for example those that handle ssh connections. Even opening a normal prompt will have the X server create a pseudo GUI terminal for you to interact with.
This is great, but recently I wanted to display a warning to all terminals on a remote machine. I wanted to show that a script was about to run on that machine. To do so, I figured I would use the old wall command to send a clear message to any user currently using a terminal on the machine.
To my surprise, none of the GUI pseudo terminals actually received the message, after some googling, I found an explanation for this issue here
https://unix.stackexchange.com/questions/150697/broadcast-messages-dont-appear-on-gnome-terminal-but-appear-on-xterm/283543#283543
This resulted in the creation of a small script to circumvent this problem. This script allows you to send a wall command to a remote machine over ssh that will work even on GUI terminals.
The script
#!/bin/bash
# WALLTEXT = STDIN (echo "message" | remote_wall.sh)
WALLTEXT=$(cat)
# THESE VARIABLES ARE READ FROM USER INPUT (echo "message" | remote_wall.sh remote_machine user pass)
SERVER_SSH_HOST="$1"
# ... as user root
ROOT_USER="$2"
ROOT_PASSWORD="$3"
ROOTPASS="sshpass -p ${ROOT_PASSWORD} ssh -o ForwardX11=no ${ROOT_USER}@${SERVER_SSH_HOST}"
main() {
echo "Running remote wall command on ${SERVER_SSH_HOST} with text: "
echo "${WALLTEXT}"
$ROOTPASS 'ps -ef | grep " pts/" | awk '"'"'{print $6}'"'"' | sort -u | grep "pts" > /tmp/terminals_list.temp'
$ROOTPASS 'ps -ef | grep " tty" | awk '"'"'{print $6}'"'"' | sort -u | grep -v "pts" | grep "tty" >> /tmp/terminals_list.temp'
pre="\nBroadcast message from $(whoami)@$(hostname) ($(date +"%a %b %d %H:%M:%S %Y")):\n\n"
message="${WALLTEXT}"
post="\n"
$ROOTPASS "cat /tmp/terminals_list.temp | while read TTY_TO; do echo -e "'"'"${pre}${message}${post}"'"'" | tee /dev/"'$TTY_TO'" 1>/dev/null; done"
$ROOTPASS 'rm /tmp/terminals_list.temp'
}
main