Então eu tenho algo como:
set -eo pipefail
ssh localhost "ls; exit 1" | cat > output
Achei que o pipefail impediria que cat escrevesse na saída (por causa do código de saída da sessão ssh), mas parece que não. Tentei então criar um fifo, mas não tenho certeza de como ler o status de saída do ssh sem consumir o conteúdo do fifo, porque parece que vai esperar até que algo o "consuma".
set -eo pipefail
[[ -e /tmp/sshdump ]] && rm /tmp/sshdump; mkfifo /tmp/sshdump;
ssh localhost "ls; exit 1" > /tmp/sshdump &
wait $! && cat > output
Então, como faço para:
- evite fazer o tubo sair no início do primeiro exemplo (e não chegar ao gato)?
- verificando o código de saída do ssh sem consumir o conteúdo fifo?
se for importante, uma solução compatível com POSIX é sempre apreciada, mas o bash também é adequado. No meu caso particular, estou usando Windows e git-bash, então talvez haja algumas peculiaridades que não conheço.
EDIT: divulgação completa, eu provavelmente deveria ter explicado o que estava planejando conseguir desde o início, em vez de simplificá-lo a ponto de a pergunta não refletir adequadamente a intenção. Eu estava tentando canalizar a saída de "mysqldump" em um shell ssh remoto diretamente para "wp db import" em minha máquina sem criar arquivos intermediários. Originalmente, pensei que o pipefail interromperia o pipeline e, assim, impediria que a importação fosse realizada se houvesse uma falha. O motivo pelo qual isso era desejável para mim era a simplicidade de não criar arquivos temporários e, claro, menos código.
Quando o shell processa
ele configura o redirecionamento e o canal antes de executar qualquer um dos comandos. Então
output
é criado ou truncado antescat
da execução.Há outra pegadinha aqui:
pipefail
apenas altera a forma como o status de saída de um pipeline é determinado, ele não controla a execução dentro do pipeline, mesmo comset -e
. Todos os comandos em um pipeline são configurados simultaneamente (ou próximos o suficiente), mas não são executados sequencialmente. Isso significa quecat
é executado ao ladossh
e, na maioria dos casos, processará a saídals
antes da sessão terminar com o código 1.Uma maneira de fazer o que você procura é armazenar a saída em algum lugar e processá-la somente se o
ssh
comando for bem-sucedido:Cuidado,
mktemp
cria arquivos legíveis e graváveis apenas pelo proprietário, portanto, você pode querer ajustar as permissões posteriormente.O
ksh93
shell tem uma maneira integrada de fazer isso:Faz o mesmo que acima e também cuida de restaurar as permissões originais do arquivo (se já estiver lá no início) ou honra o umask se ele não existia antes.
Outro benefício de gravar em um arquivo separado, renomeado no final para o destino, é que o
output
arquivo é criado ou substituído atomicamente. Em nenhum momento outro processo tentando abriroutput
o veria inacabado.