Search code examples
bashopenssh

bash: how to suppress login message from scp output


I have a simple bash function for interactive use:

push-file() {
     hosts="$1"
     src="$2"
     dest="$3"
     for h in "$hosts"
     do
        echo "=== $h ==="
        scp "$src" root@$h:"$dest"
     done
}

I can then type, for example:

push-file "host1 host2" testfile /tmp/

to copy testfile to both of the hosts. (In reality in place of the "host1 host2" I might use a variable e.g. "$foo_hosts" to specify a certain group of hosts.)

However, there is a complication: on each of the hosts, there are 10 lines of boilerplate AUP message displayed whenever you ssh to them, so the output looks like:

=== host1 ===
   Access to this system is monitored [etc...]
   [9 more lines of AUP]
testfile                                           100%  188    11.2KB/s   00:00
=== host2 ===
   Access to this system is monitored [etc...]
   [9 more lines of AUP]
testfile                                           100%  188    11.6KB/s   00:00    

But I want it to look like:

=== host1 ===
testfile                                           100%  188    11.2KB/s   00:00
=== host2 ===
testfile                                           100%  188    11.6KB/s   00:00    

(Here, the final line from scp is a progress meter -- you are seeing it here as it appears on the terminal after completion of the transfer.)

Now, the AUP message is always 10 lines long, so it should just be a case of removing the first 10 lines, but there are further complicating factors:

  • The AUP message is written by scp to stderr. This will need to be piped to the tail -n 11. I cannot afford to just direct stderr to /dev/null, as error messages after the AUP message may be lost.

  • The progress meter is written to stdout by scp, but it seemingly is only written if stdout is a terminal. Any tricks involving &> which allow stderr to be piped also seem to cause the stdout of the scp process to be a pipe rather than a terminal, and then the progress meter is suppressed.

The best I could come up with was to replace:

     scp "$src" root@$h:"$dest"

with:

     { script -q -c "scp \"$src\" root@$h:\"$dest\" 3>&1 1>&2 2>&3" /dev/null | tail -n +11; } 3>&1 1>&2 2>&3

which works, but is hideous.

QUESTION - Is there anything simpler and cleaner?

Here's the OpenSSH version, in case there is a way to modify the scp behaviour directly rather than postprocessing the output in bash: OpenSSH_7.6p1 Ubuntu-4ubuntu0.3, OpenSSL 1.0.2n 7 Dec 2017


Solution

  • You can (apparently) suppress the output by raising the error level of the underlying ssh connection. (Credit to https://askubuntu.com/a/703230.)

    scp -o LogLevel=Error "$src" "root@$h:$dest"