O execshell integrado (primeira nuance)

O execshell integrado (primeira nuance)

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/nullesteam & > /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>&1redireciona stderr para stdout e > /dev/nullredireciona stdout para /dev/null.

O &pano de fundo do processo foi extraviado. Deve ir no final da linha. Se colocado depois, steammas antes de >, nada de steamserá 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 steamtempo 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 execshell 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 execshell integrado (primeira nuance)

O padrão POSIX define um comportamento parao execcomando. Bash fornece isso através doexecShell 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/steamscript wrapper substituirá o /bin/bashshell 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 evalde escape char \) pode apresentar a oportunidade de injetar operadores de redirecionamento de shell no script, de modo que a execchamada possivelmente afete o padrão. Descritores de IO e arquivo do comando Portanto, dependendo de como você está passando 2>&1ou >somefilede 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 dashe outros.

Para efeitos da pergunta do OP, focaremos apenas no Bash porque o /usr/bin/steamscript 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:

... e a:

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 um newline.

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 listcomandos 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 stdoute stderrconforme 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 steame o envia para segundo plano rodando como umcomando assíncrono. stdinestá conectado a /dev/null, enquanto stdoute stderrpermanece conectado ao controlePseudoterminal /pty. Isto é explicado mais abaixo.

Mas primeiro...

Mais execconfusão acorrentada!

informação relacionada