qual é a diferença entre `>> / dev / stderr` (com o espaço em branco) e`> & 2`?

11

Na festança.

Estou com alguma dificuldade para determinar o que devo usar?

todos os meus scripts usam ">> / dev / stderr"

no prompt do bash, se eu tentar:
echo test >>/dev/stderrfunciona
echo test >> /dev/stderrfunciona
echo test >/dev/stderrfunciona
echo test > /dev/stderrfunciona

echo test >>&2FALHAS!
echo test >> &2FALHAS!
echo test >&2funciona
echo test > &2FALHA!

Estou disposto a mudar todos os meus scripts para >&2.

Parece também ter um grande efeito sobre o ssh (depois su SomeUser), onde >>/dev/stderrnão funcionará (permissão negada), apenas >&2funcionará.

Poder de Aquário
fonte
você pode mostrar um exemplo do erro ssh? Eu não posso reproduzir.
Jeff Schaller
@JeffSchaller você está certo, é só depois suque o problema acontece, atualizou a questão #
Aquarius Power
@AquariusPower, ... para explicar essa discrepância, a propósito: with su -c 'some command', esse comando é executado por /bin/sh, e não bashpor um comportamento específico do bash (como simular /dev/stderrpara fins de redirecionamento quando não disponível) não estiver presente.
Charles Duffy

Respostas:

22

>& né uma sintaxe do shell para duplicar diretamente um descritor de arquivo . O descritor de arquivo 2 é stderr; é assim que isso funciona. Você também pode duplicar outros descritores de arquivos, não apenas stderr. Você não pode usar o modo de anexação aqui porque a duplicação de um descritor de arquivo nunca trunca (mesmo que o stderr seja um arquivo) e >&seja um token, é por isso que você não pode colocar um espaço nele - mas >& 2funciona.

>> nameé uma sintaxe permitida diferente, onde nameé um nome de arquivo (e o token é >>). Nesse caso, você está usando o nome do arquivo /dev/stderr, que por manipulação específica do SO (no Linux, é um link simbólico /proc/self/fd/2) também significa erro padrão. Os modos de acréscimo e truncamento acabam fazendo a mesma coisa quando stderr é um terminal, porque isso não pode ser truncado. Se o seu erro padrão for um arquivo, ele será truncado:

anthony@Zia:~$ bash -c 'echo hi >/dev/stderr; echo bye >/dev/stderr' 2>/tmp/foo
anthony@Zia:~$ cat /tmp/foo
bye

Se você estiver vendo um erro com /dev/stderrover ssh, é possível que o administrador do servidor tenha aplicado alguma medida de segurança para impedir que o link simbólico funcione. (Por exemplo, você não pode acessar /procou /dev). Embora eu espere causar todos os tipos de falhas estranhas, o uso da sintaxe do descritor de arquivo duplicado é uma abordagem perfeitamente razoável (e provavelmente um pouco mais eficiente). Pessoalmente, eu prefiro.

derobert
fonte
Eu estava tendo um grande problema ao tentar replicar esse problema truncado que eu tinha antes (caso contrário, eu teria acrescentado isso à pergunta hehe), a razão pela qual mudei tudo para usar >>, thx por apontar isso! Além disso, perdi um passo su SomeUserdepois de conectar através do ssh.
Poder de Aquário
isso bash -c 'echo hi >&2; echo bye >&2' 2>/tmp/foo;cat /tmp/foonão truncará tho! (mesmo com 2>&1 |tee /tmp/foo) o que é perfeito para o log e funcionará perfeitamente depois que eu mudar tudo para >&2. Então, acho que apenas um uso direto de arquivo /dev/stderrpermite truncar, não o descritor duplicado, cool thx!
Poder de Aquário
O @AquariusPower correto, o descritor de arquivo duplicado nunca trunca. Isso está no primeiro parágrafo, talvez eu precise destacá-lo de alguma forma?
derobert
não é necessário, às vezes sou lento ehehe #
Aquarius Power
3
Esta resposta pode ser melhorada. > & é um símbolo e não dois e aí está a confusão do OP.
Joshua
8

Os casos de falha ocorrem porque a sintaxe do bash para uso &em redirecionamentos especifica uma única >e requer que ela exista diretamente adjacente ao &sinal:

[n]> & palavra

Jeff Schaller
fonte
2

Use '>'para redirecionar (trunca se houver) ou '>>'(anexa se existir).

Use '>&'para duplicar um fluxo, por exemplo, se você deseja saída padrão E erro padrão no mesmo arquivo, você redireciona para o arquivo '> output.log'e também erro com'2>&'

myjob.sh > output.log 2>&
Jose Manuel Gomez Alvarez
fonte