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
-
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… ↩︎
Comments
Leave a comment by replying to this mastodon thread. Please comment in English. If you're not on techhub.social, Click here to copy the thread link and paste it into your instance's search box.
Mastodon integration based on code by Carl Schwan and threaded adaptation by Veronica Olsen.