Please look at these:

## Does NOT return to the shell, but Ctrl-C can exit
ssh -S none -fNR 13018:localhost:22 example.com | cat

## Returns to the shell (no "-S none")
ssh         -fNR 13019:localhost:22 example.com | cat

## Returns to the shell (no "| cat")
ssh -S none -fNR 13020:localhost:22 example.com

Why the first command does not return to the shell ? I expected it to return to the shell as the other did (as the -f Requests ssh to go to background just before command execution.) and is present in the 3 samples I gave and seem to behave erraticaly upon redirection of its output (symbolized here by the | cat). The -S none is not a related option (especially that -S none should be the default behavior as I haven't any ControlMaster options set) and it seems nevertheless to change the behavior of -f. All this puzzles me.

Is there any way to catch the stdout/stderr of the last command with this command returning to the shell, to be able to react according to its output ?

The whole story:

I want to run SSH tunnel and upon failure, check if it is related to port being in use. In that case I'll try another port. I can't use error level as it is not distinctive, and while trying to catch stderr, I ran in ssh behaviors that are not clear for me and they seem even bogus (there shouldn't be any differences between using -S none and not using it, because it is the default value and I checked my ~/.ssh/config that was empty, and the /etc/ssh/ssh_config had no ControlMaster related option set.)


  • It seems that I cannot reproduce the second example as described. Could the ssh process terminates sometimes before and sometimes after cat process opens the pipe ?
  • What exactly are you trying to do? My best guess is have the ssh command go into the background, and trap stderr to a log file. Is that correct? Jan 12 '12 at 15:29
  • The problem is that ssh command doesn't go into the background (first example). I'd rather use -f for this than shell jobs (with &) as I would like to use the return code to know if the SSH tunnel was built.
    – vaab
    Jan 16 '12 at 8:07
  • 1
    please edit your question to indicate what sort of responses you are expecting and any diagnostic or error messages that you are getting. Also, I have no idea what you mean by 'back hand', 'hand given back', etc. Good luck.
    – shellter
    Jan 16 '12 at 19:01
  • @shellter thank you for your feedback. I have edited my question and I hope this is clearer now.
    – vaab
    Jan 30 '12 at 10:25

Strange, what I don't understand is why your second example returns to the shell (and I can't reproduce that).

When you run ssh -S none -fNR 13018:localhost:22 example.com | cat, an ssh process remains in the background. It still has the write end of the pipe open. So cat hasn't seen an end-of-file on its standard input yet, and therefore it keeps reading.

Pressing Ctrl+C kills the cat process (it's the only part of the job that's still running, since the ssh process in the background has moved to its own process group and the foreground ssh process terminates as soon as it's forked). If the background ssh process tried to write to its standard output (which it won't, due to the -N), the write would faile with EPIPE (ssh blocks SIGPIPE). The cat process would also exit if you killed the background ssh process.

  • I'm very ashamed to discover that I cannot also reproduce the second case. Which leaves us with 2 explanation: 1- My verifications of these were bad or my memory of them are hallucinations, or 2- could we imagine that the cat could catch the main ssh process before it terminates (depending on arbitrary conditions that could change the multitasking schedule) ?
    – vaab
    Feb 21 '12 at 17:19
  • @vaab I don't see any way in which the relative scheduling of cat and ssh would matter here. Feb 21 '12 at 17:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.