It was many years ago. At my to-be-previous job, we wanted to try some new modeling things. We grabbed the then-latest TensorFlow docker image (Since the model was based on TensorFlow—I forget which one though) and it spun up smoothly. The container even printed a pretty logo in colorful ASCII art as shown in the cover image.

The experiments went well. We eventually packed some more dependencies and an sshd (and some sort of init, of course) in, and asked IT to put the image on a shared GPU box. It became part of our development infrastructure. The shared box had access to NFS, so the sshd was mostly just for getting a remote shell. Everything went well.

… Until one day I was trying to set up automation and preferred to just rsync things from my laptop into the container—it didn’t exactly work as expected:

$ rsync -avPz output.mp4 targetmachine:/path/to/work/directory
protocol version mismatch -- is your shell clean?
(see the rsync manpage for an explanation)
rsync error: protocol incompatibility (code 2) at compat.c(622) [sender=3.2.7]

I double-checked. rsync installed. Check. rsync version inside the container. Check. ssh was working. Check. Hmm… That “is your shell clean?” piqued my interest though—what do you even mean by my shell not being clean? scp produced a much more actionable error message here:

$ scp output.mp4 targetmachine:/path/to/work/directory
scp: Received message too long 458961211
scp: Ensure the remote shell produces no output for non-interactive sessions.

This was when I realized that the beautiful logo was being printed to stdout upon login—regardless of being in an interactive session or not! A search with a part of the logo strings in /etc quickly pointed out the culprit. It was an easy fix from here.

In my humble opinion, everyone dealing with the command line should give this nice article called “Becoming a Terminal Pro—Part 2” a read—especially the section about “Standard Output, Standard Error and File Redirection”1.

Here’s the heavily biased TLDR takeaway: If the main purpose of your command-line tool is NOT printing the logo, DO NOT print the logo to stdout! This includes the shell RC files like bashrc or zshrc—although if you hide them behind an interactivity test (see the end of this article) they shouldn’t cause problems. If you really want to show some console branding things, do it on stderr.


Thankfully, the official TensorFlow image was fixed later at version 2.1.1. The fix was simple—they added this inside /etc/bash.bashrc before printing the logo and warning texts:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

That’s it. If it were me, I would also add something like >&2 after every logo-printing commands. But this is fine, too. On further notes, there is another (in my opinion more first principle) way to do this—as seen in the shell RC files in Arch Linux:

# If not running interactively, don't do anything
[[ $- != *i* ]] && return

  1. Well, unless you only deal with Windows. Windows does have stdout and stderr, but programs there tend not to care much about being able to pipe with other programs the Unix way… ↩︎