20

I copied a snippet of Bash to background an ssh command executed remotely:

ssh user@remote <<CMD
some process <&- >log 2>error &
CMD

What does <&- do?
My guess is that it is the same as < /dev/null

My next understanding is that the three main file descriptors (stdin, stdout, stderr) need to be closed to prevent:

  1. The job being backgrounded and the script exiting -- conflicting somehow?
  2. When the terminal closes, all processes that are accepting stdin from terminal are closed?
4
  • Obligatory cross-reference: See What are the shell's control and redirection operators? — although all it says about this operator is that it "can be used to close or duplicate file descriptors" and you should "see the relevant section of your shell's manual". Sep 18, 2015 at 7:24
  • If I recall correctly, ssh -nNT user@remote 'command' will create a non-interactive SSH session. Append & to background it, prepend nohup to the command to keep it running if your connection dies. Sep 18, 2015 at 14:15
  • 1
    @MarkKCowan man ssh suggests that -N disables running a remote command entirely, and a quick test supports that.
    – Tom Hunt
    Sep 18, 2015 at 15:08
  • Ah yes, I used -nNTR for reverse port forwarding. Ignore the -N and -R then :) Sep 18, 2015 at 15:10

3 Answers 3

30

<&- is not quite the same thing as < /dev/null. <&- closes fd 0, whereas < /dev/null redirects it from the device /dev/null, which never provides any data and always gives EOF on read. The difference is mostly that a read(2) call from a closed FD (the <&- case) will error with EBADF, whereas a call from a null-redirected FD will return no bytes read (end-of-file condition). If your program never reads from stdin, the distinction doesn't matter.

Closing the FDs is good practice if you're backgrounding something, since a backgrounded process will hang if it tries to read anything from TTY. This example doesn't fully handle everything it should, though; ideally there would be a nohup or setsid invocation somewhere, to fully disassociate the background process.

8
  • So I should use nohup in addition to closing file descriptors? Sep 17, 2015 at 16:31
  • 2
    The most thorough method (which imitates the way programs daemonize themselves) is something like setsid some process <&- >path/to/log 2>path/to/error. The quicker method is something like nohup some process &.
    – Tom Hunt
    Sep 17, 2015 at 16:34
  • 2
    @EricFrancis: Using nohup make no sense here. nohup prevent process from receiving HUP signal when its control terminal closed. But you didn't have any terminal in this case.
    – cuonglm
    Sep 17, 2015 at 16:44
  • @TomHunt: The background process didn't hang, the ssh session did.
    – cuonglm
    Sep 17, 2015 at 16:48
  • 2
    not a good idea to close fds 0, 1 & 2 ... you don't want the next fd created to take up one of those values. better to redirect them to /dev/null Sep 19, 2015 at 0:01
7

See man bash:

  [n]<&word

is used to duplicate input file descriptors. If word expands to one or more digits, the file descriptor denoted by n is made to be a copy of that file descriptor. If the digits in word do not specify a file descriptor open for input, a redirection error occurs. If word evaluates to -, file descriptor n is closed. If n is not specified, the standard input (file descriptor 0) is used.

5
  • The correct definition is that it is unspecified what happens when you have [n]<&word and word contains more than a single digit.
    – schily
    Sep 17, 2015 at 16:57
  • What do you mean? Is the man bash incorrect? Sep 17, 2015 at 18:36
  • @EricFrancis because it is unspecified in the standard, bash chooses to implement it in a sane way (for some suitable definition of "sane"). Other shells may or may not do so.
    – muru
    Sep 17, 2015 at 18:51
  • @muru The question is tagged bash, not posix-shell.
    – Barmar
    Sep 24, 2015 at 14:15
  • @Barmar ok. So...?
    – muru
    Sep 24, 2015 at 14:16
7

<&- close standard input.

The general form, defined by POSIX, is:

[n]<&word

Its purpose to made file descriptor n is a copy of file descriptor denoted by word. Standard in is assumed if n is omitted, and if word is -, the file descriptor n will be closed.

It's not the same as </dev/null, since when in case of </dev/null, the standard input still opened, and was redirected to other place.

You need to closed all file descriptors of processes which were attached to ssh socket, otherwise, ssh session can not close.

You can run the command on remote machine without attach it to ssh session, by using screen or tmux:

ssh user@remote 'screen -S test -d -m command'
1
  • Why the down vote?
    – cuonglm
    Sep 19, 2015 at 23:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .