56

I've got SSH passwordless set up, however it prints the MoTD when it logs in. Is there anyway to stop that happening from the client side?

I've tried ssh -q but that doesn't work. I don't want to use ~/.hushlogin nor do I want to change the server set up. The only thing that can work is to quiet all output, with >/dev/null 2>&1. However, I don't want to ignore errors in case there actually is a problem. Even doing >/dev/null doesn't work, since ssh seems to print the motd to the stderr.

Update & reasoning I'm running backup in a cron. I don't want to get a cron email unless an error has occured. However if the motd is printed I'll get an email all the time.

I want to keep the motd being printed because that has legal implications. The motd says "unathorized access prohibited". You need to have this sort of statement in there to legally prevent people from access it (like a no trespassing sign). Hence I don't want to blanket disable it all the time.

nietonfir
  • 103
Amandasaurus
  • 33,461

16 Answers16

72

I'm not sure why you have an aversion to doing this correctly - either on the server a la

PrintMotd no
PrintLastLog no

and

#/etc/pam.d/ssh
# Print the message of the day upon successful login.
# session    optional     pam_motd.so

Or adding ~/.hushlogin for each user.

Hint, for ~/.hushlogin, add it to /etc/skel so new user home directories are created with the file.

Update:

Without more information about your backup cron job, my only other suggestion is to redirect the output of the command to a file (or let cron capture it in email) and the output of the ssh session to /dev/null. Something like:

0 0 * * * ssh backuphost "backup_script_that_writes_to_a_log" >/dev/null

Or

0 0 * * * ssh backuphost "backup_command 2>&1" >/dev/null

I'd have to play around with the commands a bit, but that should get you started.

jtimberman
  • 7,665
24

@note All examples assume you've set a variable connectionString with something like connectionString=user@server.

How I got to the solution

Using ssh -T should work for simple commands. For example this doesn't print any extra information:

ssh -T $connectionString "echo 'blah'"

The problem is when you try to use here-doc to run many commands. For example - bellow will NOT work - it will echo message of the day (MoTD) and also might show you "stdin: is not a tty".

somethingLocal='something local'
ssh -T $connectionString <<EOC
    echo 'blah'
    echo "blah $somethingLocal"
EOC

To workaround the issue you need first save commands to local variable and the send them to remote server.

somethingLocal='something local'
read -r -d '' commands <<EOC
    echo 'blah'
    echo "blah $somethingLocal"
EOC
ssh -T $connectionString "$commands"

But that's messy...

Final solution

Make a universal function (note that it can take a string or HEREDOC as commands).

function silentSsh {
    local connectionString="$1"
    local commands="$2"
    if [ -z "$commands" ]; then
        commands=`cat`
    fi
    ssh -T $connectionString "$commands"
}

Examples

Use this like so:

somethingLocal='something local'
silentSsh $connectionString <<EOC
    echo 'blah'
    echo "blah $somethingLocal"
EOC

Or like so:

silentSsh $connectionString "echo 'blah'"

Or like so:

silentSsh $connectionString <<'EOC'
    echo 'blah'
    somethingRemote=`echo 'whatever'`
    echo "blah $somethingRemote"
EOC

Or even like so:

silentSsh $connectionString < getlines.sh
Nux
  • 703
22

If you want this on a per-user basis, just do a touch ~/.hushlogin and you're all set with OpenSSH.

Update: As pointed out elsewhere, pam_motd may be configured to not use a per-user .hushlogin; check /etc/login.defs for HUSHLOGIN_FILE. It may be configured to have all users listed in /etc/hushlogins or similar.

towo
  • 1,937
11

How about this hack? ;-P

ssh -t user@machineName '/bin/bash'

The following is not valid:

Passing -T to ssh to disable tty allocation:

ssh -T machineName 'echo foo'
kenorb
  • 7,125
Kyle Brandt
  • 85,693
3

What operating system is this? On some systems (like ubuntu) the motd isn't printed by the ssh server (PrintMotd in /etc/ssh/sshd_config), but by pam with pam_motd. If this is the case then you probably can't control it from the client.

2

You have to do it on the server:

PrintMotd no
PrintLastLog no

On debian/ubtuntu also hash the line with pam_motd.so:

#/etc/pam.d/ssh
# Print the message of the day upon successful login.
# session    optional     pam_motd.so
ThorstenS
  • 3,170
2

Don't execute ssh command directly by cron.

Make an helper bash script instead, executing the ssh job and fetching the output, the errors and the error code if needed; eventually parse them in order to remove unwanted strings from error messages (the MoTD in your case) and then re print on the bash script output and error streams what you have obtained in such a way.

Than put this bash script in cron and live happy :)

Note: This is a general solution, and has to work whatever is the job you have to perform via ssh. It is only client side too, which should fulfill your needs ... the only dependence of the client on the server config is the knowledge of the exact message you want to cut out from the std err or out of ssh client

drAlberT
  • 11,099
2

Just a sidenote (would have been a comment, if I could post that): Contents of motd are shown after successfull login to the system. If I'd like to legally prevent people from accessing a box I'd rather do that by a "Banner" in sshd_config. The contents are displayed after entering Username but before authenticating.

2

Either you haven't tried what you're describing, or your servers are configured wrong!

Here's what I just tried on RHEL5:

workstation ~ $ ssh root@server
server ~ # echo "MOTD" > /etc/motd
server ~ # ^D
workstation ~ $ ssh root@server
MOTD
server ~ # ^D
workstation ~ $ ssh root@server echo notice the lack of motd
notice the lack of motd
workstation ~ $ 

I don't suppose you need the disclaimer to be sent to non-interactive shells, do you? (If anyone claims you do, do me a favor, kick them in the nuts.) Because that's exactly why there's a distinction between interactive shells and non-interactive ones.

But in any case, here's what I do because I don't like mail from cron: I pipe the output to logger. Just pipe it through tail to remove the first few (let's say 3) lines of your pointless disclaimer as such (untested code, I don't have access to my scripts):

( tail -n +3 | logger -i -t mycronjob -s -p cron.crit ) <&6 &
exec 2>&6
cron_fsckin_job
niXar
  • 2,093
1

I hade the same problem on FreeNAS which is based on freeBSD I think.

The only thing that worked was to do

ssh user@device "show run" | tee "file_$(date +"%y%m%d".cfg" 2>/dev/null. 

Throwing away the errors are not a problem for me since I wrote a script that looks for each new device config. If it fails then my monitor script will alarm me.

I'd be happy to share the monitor script. It also rotates the files for devices that push their configs through TFTP. Those devices can't by themselves make custom names with dates and such, so it needs to rotate name.cfg to name_[todays date].cfg each day.

1

SOLUTION HERE:

In case you are not in charge of the server and you cannot change motd or sshd config, use command like the following:

Redirect STDERR to STDOUT for remote command(s) so that you will see it. And then redirect STDERR of ssh to /dev/null. MOTD goes to STERR and ends up in /dev/null. Any standard AND error message from remote command will be shown (as it goes to STDOUT)

Variant 1 - if you care about the exit status of the remotely-executed command:

ssh remotehost "(remote_command1 && remote_command2; remote_command3) 2>&1" 2>/dev/null || echo SSH connection or remote command failed - either of them returned non-zero exit code $?

Variant 2 - if you want to ignore the exit code of remote command - just execute true as the last remote command

ssh remotehost "(remote_command; true) 2>&1" 2>/dev/null || echo SSH connection failed

Examples of error messages:

Example 1:

ssh remotehost "failed_remote_command 2>&1" 2>/dev/null || echo SSH connection failed or remote command returned non-zero exit code
bash: failed_remote_command: command not found
SSH connection or remote command failed - either of them returned non-zero exit code 127

Example 2:

ssh remotehost "failed_remote_command 2>&1; true" 2>/dev/null || echo SSH connection failed
bash: failed_remote_command: command not found

Example 3a:

ssh remotehost "failed_remote_command 2>&1; true" 2>/dev/null || echo SSH connection failed
# no message is shown

Example 3b:

ssh nonexistinghost "failed_remote_command 2>&1; true" 2>/dev/null || echo SSH connection failed
SSH connection failed
Chris
  • 11
1

If I understand you, you need motd for other reasons but don't need motd for backup. In the config of sshd cannot set it up by user basis only globally. Therefore you need solve motd supression in client side. But there is not difference between motd's text and the backup software's error messages. Both are text in the terminal. The only solution I see to make difference between this two message then filter the motd's one. Because software's messages are hard to modify I suggest to modify motd's text. For example put a frame around:

*** BEGIN message from the machine room ***

motd message

*** END message from the machine room ***

Then you should filter out the text between the frame and drop it.

Saabi
  • 371
0

I came across this thread searching for a solution to suppress the MOTD when using sftp in non-interactive mode but I didn't have access to the server. So the solution that worked for me when passing the -q flag to sftp, which is to make it quiet.

alexkb
  • 103
  • 5
0

Have you tried removing the text in the motd file? Just a thought.

Hint: /etc/motd
Joseph Kern
  • 9,989
0

What are you trying to do and why does the MoTD bother you? I'm guessing executing a remote command and parsing the output? If so, this could be done in a variety of ways without invoking an interactive shell (which causes the motd to be shown).

0

Have you tried using an ssh subsystem configuration? You can find an example at http://www.hell.org.ua/Docs/oreilly/tcpip2/ssh/ch05_07.htm that even includes backing up files.

David
  • 3,655