Somebody runs write at your terminal and text you didn't ask for shows up mid-command: mesg is the switch that stops it. The examples use the system command at /usr/bin/mesg, supplied by util-linux 2.39.3 on this machine. Allow about five minutes. You need a shell attached to a terminal; changing this setting normally needs no elevated privileges.
Safety boundary: mesg changes the write permission on the terminal device tied to standard error. It does not touch login accounts, SSH configuration or any system-wide messaging policy. The setting affects only the terminal you run it in, so keep the command in the window you actually mean.
Check the system binary explicitly. This sidesteps a distracting shell PATH issue: another util-linux installation could supply a different version under the same command name.
$ command -v /usr/bin/mesg
/usr/bin/mesg
$ /usr/bin/mesg --version
mesg from util-linux 2.39.3
The installed manual documents n to disallow messages, y to allow them, and no argument to report the current state.
Run the command with no argument:
$ /usr/bin/mesg
is y
is y means messages are allowed, is n means they're blocked. That's the whole output. The exit status carries the same answer, so capture it immediately if a script or a diagnosis depends on it:
$ /usr/bin/mesg
is y
$ status=$?
$ printf 'mesg status: %s\n' "$status"
mesg status: 0
Checkpoint: If you see no useful status, confirm this shell is attached to a terminal before you change anything. Don't test this by copying the command into a pipeline or a background job.
To stop programs such as write and talk from displaying messages in this terminal, run:
$ /usr/bin/mesg n
$ /usr/bin/mesg
is n
$ printf 'mesg status: %s\n' "$?"
mesg status: 1
This changes the terminal device's write permission for the current session. It doesn't kill an existing shell and doesn't delete any messages: a sender may still get a separate error, depending on the sending program and terminal permissions.
There's no elevated command here. sudo can make the operation less clear and may end up touching a different terminal context, so leave it out.
Use y to restore the permission:
$ /usr/bin/mesg y
$ /usr/bin/mesg
is y
$ printf 'mesg status: %s\n' "$?"
mesg status: 0
This is the undo for the previous step. If you're not sure which state you left behind, run the no-argument check rather than toggling blindly. Unlike older historical implementations, the util-linux command does not invert the state when called with no argument; it reports it.
Branch on the documented status rather than matching the human-readable text. This version keeps the diagnostic output out of the script's own output:
if /usr/bin/mesg >/tmp/mesg-status 2>/tmp/mesg-error; then
printf '%s\n' 'terminal messages are allowed'
else
status=$?
case "$status" in
1) printf '%s\n' 'terminal messages are blocked' ;;
*) printf 'mesg failed with status %s\n' "$status" >&2; exit "$status" ;;
esac
fi
rm -f /tmp/mesg-status /tmp/mesg-error
Status 0 and 1 are both normal results; anything above 1 is an error. The temporary paths above are fine for a small local status check but not for sensitive data, so use a private temporary directory in a real script. There is no documented --quiet option, so don't invent one.
When standard error isn't connected to a terminal, mesg has nothing to control. The manual says it exits silently with status 2. --verbose asks it to explain that situation instead:
$ /usr/bin/mesg --verbose
$ printf 'mesg status: %s\n' "$?"
mesg status: 2
The exact wording can vary with the invocation and the util-linux release, but status 2 is the reliable diagnostic. Run the command directly in an interactive terminal, not through a command substitution, a redirected standard error, or a CI step with no pseudo-terminal.
mesg reported the current state before you changed it.mesg n to block messages or mesg y to allow them.