echo writes its output to its stdout. That's its file descriptor 1.
echo -e '\a', depending on the
echo implementation, that will either write a BEL character (0x7 byte value in ASCII) followed by LF (aka newline) or
-e \a followed by LF or
-e followed by BEL and LF.
To write a BEL character only, you'd rather write
That doesn't make much difference to the core of this question anyway.
echo will write what it has to write to its stdout.
If you enter that command at the prompt of an interactive shell without redirection, stdout will be inherited from the shell. If the shell was started by a terminal emulator like
screen, the file descriptor 1 will have been opened (by
xterm) on a
/dev/pt<something> device file (see
lsof -ad1 -p "$$" or
readlink -f /proc/self/fd/1 on Linux). That will be the slave side of pseudo-terminal pair.
The only thing important to know about it here is that it's some sort of communication channel. A bit like a pipe except that it has a few more bells and whistles that help with user interaction.
printf writes the BEL to that device file, what happens is that it's transmitted to something at the other end. In the
xterm case, that's the terminal emulator itself. The BEL character is a control character that make terminal and terminal emulators alert the user in some way (
\a is for alert). That can be an audible beep, chime or a visual flashing of the screen or both.
xterm will typically use the
XBell() X11 API call for that or flash its window if it's been configured to use a visual bell.
screen itself would simply forward the BEL to the host terminal(s) it is connected to and where that screen window is active or issue a terminal flash control sequence or "Wuff, Wuff!!" (sic) message depending on how it was configured (see
info screen vbell).
If you login on a PC running Linux outside of the graphic session, fd 1 will have been opened (by
getty) to a
/dev/tty<1-...> device. Here, it's the kernel that implements a terminal emulator and uses the monitor for output and keyboard(s) for input. Same principal, when
printf writes that BEL there, the kernel makes the PC speaker beep.
When you run that command at the prompt of an interactive shell over
ssh, fd 1 will also be a pseudo-terminal device (
/dev/pt<something>), this time started by the ssh server which started the login shell of the remote user on the remote system. At the other end of the pseudo-terminal pair is the ssh server. When receiving that BEL (or anything else for that matters), the ssh server sends that across the encrypted connection to the ssh client, and the ssh client writes it to its stdout, which will eventually make it to the terminal window you're sitting at.
printf '\a' > /dev/console
The shell opens the
/dev/console file on the file descriptor 1 (stdout) before running
/dev/console, at least on Linux, is the tty device file that is meant to receive system messages.
/dev/console typically redirects to another tty device. On PC, by default, that's
/dev/tty0 which points to the currently active virtual terminal, but that can be changed at boot time using the
console=/dev/anything kernel parameter (for instance
console=/dev/ttyS0 to make it the first serial device), and it can even be changed (for the output part) later on, using the
In any case, that will be a terminal that is typically attached to the machine itself. So outputting a BEL there is meant to alert the administrator of that machine as it's using the channel used to send system messages to the user.
To write a message to all logged in users, you can also use the
wall application, or the
write application to just one user (one terminal device), provided those users have not disabled those notifications (with