14

I edited an answer on Ask Ubuntu that was suggesting the following

nohup gedit >& /dev/null & 

When they actually meant

nohup gedit &> /dev/null & 

The latter correctly redirects both stderr and stdout to /dev/null. I was expecting the former to either create a file called & or, more likely, to give an error as it does for other cases:

$ echo "foo" >& 
bash: syntax error near unexpected token `newline'

Instead, it seems to work in exactly the same way as the former, a gedit window appears and no error message is printed.

I should also note that this is shell specific:

  • bash (4.2.45(1)-release), zsh (5.0.2), csh (deb package version: 20110502-2) and tcsh (6.18.01) : works as described above, no error message, no files created.

  • dash (0.5.7-3):

    $ nohup gedit >& /dev/null & 
    $ dash: 2: Syntax error: Bad fd number
    
  • ksh (93u+ 2012-08-01): fails, but a process is apparently started (1223) though no gedit window appears:

    $ nohup gedit >& /dev/null & 
    [1] 1223
    $ ksh: /dev/null: bad file unit number
    
  • fish (2.0.0):

    > nohup gedit >& /dev/null & 
    fish: Requested redirection to something that is not a file descriptor /dev/null
    nohup gedit >& /dev/null & 
                   ^
    

So, why does this command simply run with no errors (and no output file created) in some shells and fail in others? What is the >& doing in the apparently special case of nohup? I am guessing that >& /dev/null is being interpreted as >&/dev/null but why isn't the space causing an error in these shells?

terdon
  • 242,166
  • In my machine, Ubuntu 12.04, this command run normally for dash. – cuonglm Mar 05 '14 at 19:49
  • nohup command, run independent tty your application.According to my memory, dash extended of ash , Debian ash , ash developed byOpenBSD and it's limited shell,even maemo OS(Debian Base on n900 mobile) uses dash,ash family shell have limited usage expect of bash or tcsh. – PersianGulf Mar 05 '14 at 19:50
  • @Gnouc huh, perhaps a different version (I'm on Debian)? I can't figure out how to get my dash to print its version out but the package is 0.5.7-3, what's yours? Also, are you sure you're running dash? That's Ubuntu's default sh isn't it? – terdon Mar 05 '14 at 19:54
  • @MohsenPahlevanzadeh I'm not sure what your point is, I know what nohup does, my question is why the >& seems to work with nohup alone in some shells. – terdon Mar 05 '14 at 19:55
  • You can use the following link for abstarct viewing of shells: http://unix.stackexchange.com/questions/45684/what-is-the-difference-between-profile-and-bash-profile/45805#45805 – PersianGulf Mar 05 '14 at 19:55
  • @MohsenPahlevanzadeh again, thank you but you have completely missed the point of my question. – terdon Mar 05 '14 at 19:57
  • @terdon: mine is 0.5.7-2. I use bash as default shell. But I haved switched to dash before running this command. – cuonglm Mar 05 '14 at 20:21
  • When I do that in bash and then do jobs, I see this as command (note >& changed to &>) $ jobs [1]+ Running nohup gedit &>/dev/null & – X Tian Mar 05 '14 at 20:43
  • @XTian umm, the whole point is the >&, &> is just shorthand for 2>&1 > so of course it works. I think that the shells where this works are simply ignoring the space between the >& and /dev/null, >& means redirect to the file descriptor that follows, >&2 means redirect to stderr for example. – terdon Mar 05 '14 at 20:46

1 Answers1

21
nohup gedit &> /dev/null

is POSIX syntax and is the same as:

nohup gedit &
> /dev/null

That is run nohup gedit in background and then do a > /dev/null redirection without running a command.

nohup gedit >& /dev/null

is not POSIX syntax and is the csh way to redirect both stdout and stderr to /dev/null. csh doesn't have the 2>&1 operator as found in Bourne, so it's the only way csh has to redirect stderr.

zsh (as often) also provides with the csh syntax, but it also supports the x>&y fd duplication operator of the Bourne shell, which means there's a conflict there.

ls >&file

redirects ls's stdout and stderr to file, but if the file is 2, you've got a problem as

ls >&2

means redirect stdout to the resource pointed to by fd 2 (dup(2, 1)). So you need to write it:

ls >& ./2

if you wanted to redirect both the stdout and stderr of ls into a file called 2 in the current directory; or use the standard syntax.

bash initially did no understand >&, but it introduced the &> operator instead for that, breaking POSIX compliance in the process (though it's unlikely a script would use cmd &> xxx).

ksh copied that operator in ksh93t+ in 2009, mksh in R35 in 2008 (disabled in posix mode) but not >&.

bash added support for >& in 2.05.

busybox sh added support for both &> and >& in 1.13 (2008).

Neither >& nor &> as meaning redirect stdout and stderr are POSIX/Bourne.

If you want to redirect both stdout and stderr portably, the syntax is

cmd > file 2>&1