Estou tentando redirecionar toda a saída de um programa (Steam) para/dev/null para que não apareça no terminal.
Aqui está o que eu tentei:
steam & > /dev/null 2>/dev/null
esteam & > /dev/null 2>&1
Nenhum dos quais suprime suas mensagens (até onde eu sei).
Meu entendimento é que & desconecta o processo do terminal e > redireciona entrada/saída, com o padrão/blank > sendo stdout e 2> sendo stderr. Existem mais resultados do que esses dois? Por que ainda estou vendo resultados se estou redirecionando tudo?
Responder1
Tentar:
steam 2>&1 > /dev/null &
2>&1
redireciona stderr para stdout e > /dev/null
redireciona stdout para /dev/null
.
O &
pano de fundo do processo foi extraviado. Deve ir no final da linha. Se colocado depois, steam
mas antes de >
, nada de steam
será redirecionado, embora o processo seja executado corretamente em segundo plano.
Responder2
Este problema específico steam
é um caso especial que às vezes pode exigir algum entendimento e tratamento especiais. O steam
tempo de execução é um script wrapper que contém o seguinte:
#!/bin/bash
# default to minimize on close, so we never have a running steam process
# in the background because of a broken Tray Icon on some desktops/WMs
#export STEAM_FRAME_FORCE_CLOSE=${STEAM_FRAME_FORCE_CLOSE:-0}
exec /usr/lib/steam/steam "$@"
Observe que ele usa o exec
shell integrado, além de passar todos os argumentos com $@
.
Portanto, embora a solução usual para redirecionamento de saída do shell seja semelhante aResposta de @Adobe e @Gary, esse tipo específico de caso muitas vezes pode exigir uma abordagem e uma compreensão um pouco mais matizadas do que está acontecendo nos bastidores. Há alguma sutileza sobre o motivo pelo qual todos os métodos possíveis de redirecionamento de saída e ordem de operações steam
às vezes podem não funcionar conforme o esperado.
O exec
shell integrado (primeira nuance)
O padrão POSIX define um comportamento parao exec
comando. Bash fornece isso através doexec
Shell integrado. O que pode afetar o redirecionamento de IO padrão e a árvore de subprocessos, dependendo de como é chamado. Observação:Embora isso não se aplique tecnicamente ao caso de uso específico do OP e aos comandos listados, estou incluindo-o aqui porque é uma armadilha comum e uma advertência a ser observada.
Do IEEE Std. 1003.1, Edição de 2004:
O utilitário exec deve abrir, fechar e/ou copiar descritores de arquivo conforme especificado por quaisquer redirecionamentos como parte do comando.
Se exec for especificado sem comando ou argumentos, e quaisquer descritores de arquivo com números maiores que 2 forem abertos com instruções de redirecionamento associadas, não será especificado se esses descritores de arquivo permanecerão abertos quando o shell invocar outro utilitário. Os scripts preocupados com o fato de os shells filhos poderem usar indevidamente os descritores de arquivos abertos sempre podem fechá-los explicitamente, conforme mostrado em um dos exemplos a seguir.
Se exec for especificado com comando, ele substituirá o shell por comando sem criar um novo processo. Se argumentos forem especificados, eles deverão ser argumentos para comando. O redirecionamento afeta o ambiente atual de execução do shell.
A exec /usr/lib/steam/steam "$@"
linha no /usr/bin/steam
script wrapper substituirá o /bin/bash
shell em execução (conforme a "linha shebang) sem criar um novo subprocesso. O $@
especificador de argumento é passado entre aspas duplas, o que deve, na maioria dos casos, evitar quaisquer efeitos colaterais com operadores de redirecionamento IO No entanto, é bom estar ciente de que passar alguns operadores de redirecionamento de saída como argumentos (por exemplo, por meio de aspas erradas "
ou '
por meio eval
de escape char \
) pode apresentar a oportunidade de injetar operadores de redirecionamento de shell no script, de modo que a exec
chamada possivelmente afete o padrão. Descritores de IO e arquivo do comando Portanto, dependendo de como você está passando 2>&1
ou >somefile
de outros operadores de redirecionamento para o script wrapper, eles seriam avaliados no contexto de: "$@"
Felizmente, as aspas duplas neste caso eliminariam a maioria dos efeitos colaterais. , mas é importante ter cuidado com qual processo bash ou subshell está avaliando esses argumentos.
Redirecionamento de saída Unix: stdin
, stdout
, &stderr
A maioria dos UnixREPLshells têm um método semelhante para redirecionar ofluxos IO padrão, stdin
, stdout
, e stderr
. Isso inclui, mas não está limitado a: POSIX sh
, Bash, Z Shell zsh
, Korn Shell ksh
, C Shell csh
, Dash dash
e outros.
Para efeitos da pergunta do OP, focaremos apenas no Bash porque o /usr/bin/steam
script wrapper começa com Bash "Shebang" linha: #!/bin/bash
.
No Bash, os primeiros 3 descritores de arquivo ( fd
's) são sempre definidos da seguinte forma, indexados a partir de zero 0
:
stdin
=fd 0
stdout
=fd 1
stderr
=fd 2
A saída de qualquer comando pode ser redirecionada usando ooperadores de redirecionamento de saída no Bash (Manual de referência do Bash: § 3.6 Redirecionamentos). Uma introdução básica a isso pode ser encontrada neste artigo:Diversão de redirecionamento de Bash com descritores. Para uma explicação mais intuitiva, com recursos visuais,veja este excelente artigo (Altamente recomendado!).
Ordem das Operações (segunda nuance):
Existe uma ordem sutil de operações entre:
- Operadores de redirecionamento(
>
,<
,>>
,<<
,&>
,&>>
,X<&Y
,X>&Y
,X>|Y
,X<&Y-
,X<>Y
, etc...)
... e a:
- Operadores de controle(
&
,;
,\n
/newline
,||
,&&
;;
,;&
,;;&
,|
|&
,(
,)
).
DeManual de referência do Bash § 3.6 Redirecionamentos:
Os redirecionamentos são processados na ordem em que aparecem, da esquerda para a direita.
[...RECORTE...]
Observe que a ordem dos redirecionamentos é significativa. Por exemplo, o comando
ls > dirlist 2>&1
direciona a saída padrão (descritor de arquivo 1) e o erro padrão (descritor de arquivo 2) para o arquivo dirlist, enquanto o comando
ls 2>&1 > dirlist
direciona apenas a saída padrão para o arquivo dirlist, porque o erro padrão foi feito uma cópia da saída padrão antes que a saída padrão fosse redirecionada para dirlist.
Da mesma forma, existe uma ordem de operações para &
e outros operadores de controle.
DeManual de referência do Bash: 2.4 Listas de comandos:
Uma lista é uma sequência de um ou mais pipelines separados por um dos operadores '
;
', '&
', '&&
' ou '||
' e opcionalmente finalizado por um de ';
', '&
' ou umnewline
.Destes operadores de lista, '
&&
' e '||
' têm precedência igual, seguidos por ';
' e '&
', que têm precedência igual.Uma sequência de uma ou mais novas linhas pode aparecer em
list
comandos para delimitar, equivalente a um ponto e vírgula.
Finalmente, especificamente a seção sobre &
:
Se um comando for finalizado pelo operador de controle '
&
', o shell executará o comando de forma assíncrona em um subshell. Isso é conhecido como executar o comando nofundo, e estes são chamados deassíncronocomandos. O shell não espera o comando terminar e o status de retorno é0
(true
). Quando o controle de trabalho não está ativo (vejaControle de trabalho), a entrada padrão para comandos assíncronos, na ausência de redirecionamentos explícitos, é redirecionada de/dev/null
.
Por que os comandos do OP não fizeram o que era esperado
Os dois primeiros comandos tentados foram:
steam & > /dev/null 2>/dev/null
steam & > /dev/null 2>&1
A razão pela qual estes não realizaram o redirecionamento pretendido de ambos stdout
e stderr
conforme o esperado é devido ao acima mencionadoordem de operações/precedência do operadorregras listadas acima. Especificamente, o &
operador é visto primeiro na ordem da esquerda para a direita. Ele é aplicado à primeira palavra, o comando steam
e o envia para segundo plano rodando como umcomando assíncrono. stdin
está conectado a /dev/null
, enquanto stdout
e stderr
permanece conectado ao controlePseudoterminal /pty
. Isto é explicado mais abaixo.
Mas primeiro...