No bash, percebo que, se um comando usando o redirecionamento falhar, todos os programas executados antes dele não serão executados.
Por exemplo, este programa abre o arquivo "a" e grava 50 bytes no arquivo "a". No entanto, executar este comando com o redirecionamento para um arquivo com permissões insuficientes (~ root / log), não produz alterações no tamanho do arquivo "a".
$ ./write_file.py >> ~root/log
-bash: /var/root/log: Permission denied
cdal at Mac in ~/experimental/unix_write
$ ls -lt
total 16
-rw-rw-r-- 1 cdal staff 0 Apr 27 08:54 a <-- SHOULD BE 50 BYTES
Alguém poderia pensar que o programa seria executado, capturar qualquer saída (mas também gravar no arquivo "a") e depois falhar em gravar qualquer saída no ~ root / log. Em vez disso, o programa nunca é executado.
Por que isso e como o bash escolhe a ordem das "verificações" antes de executar um programa? Também são realizadas outras verificações?
ps Estou tentando determinar se um programa executado no cron realmente foi executado quando redirecionado para um arquivo "permissão negada".
fonte
stdout
para fazer exatamente isso. Portanto, você não verá nenhuma saída, mesmo que seu programa tenha sido executado.write_file.py
programa e envie sua saída para o~root/log
bash:" Desculpe, mas você não tem permissão para gravar nesse arquivo! "O shell está fazendo exatamente o que deve fazer. Se não puder fazer o que você pediu , informa imediatamente por que há um problema, dando a você a oportunidade de decidir como lidar com ele.Para todos os mantenedores do bash, coisas muito ruins podem acontecer se você executar esse comando e não conseguir salvar a saída. Se fosse o suficiente importante que você designado um lugar para guardá-lo, seria errado ASS | L | ME foi OK para executar sem salvar stdout.Respostas:
Não se trata realmente de pedir cheques, simplesmente a ordem na qual o shell configura as coisas. Os redirecionamentos são configurados antes da execução do comando; portanto, no seu exemplo, o shell tenta abrir
~root/log
para anexar antes de tentar fazer algo que envolva./write_file.py
. Como o arquivo de log não pode ser aberto, o redirecionamento falha e o shell para de processar a linha de comando nesse ponto.Uma maneira de demonstrar isso é pegar um arquivo não executável e tentar executá-lo:
Isso mostra que o shell nem olha
./demo
quando o redirecionamento não pode ser configurado.fonte
Na página do manual do bash, seção REDIRECTION (ênfase minha):
Portanto, o shell tenta abrir o arquivo de destino
stdout
, o que falha, e o comando não é executado.fonte
Vale observar que o shell deve estabelecer redirecionamentos antes de iniciar o programa.
Considere o seu exemplo:
O que acontece no shell é:
fork()
; o processo filho herda os descritores de arquivo aberto de seu pai (o shell).fopen()
(a expansão de) "~ root / log", edup2()
para fd 1 (eclose()
o fd temporário). Sefopen()
falhar, ligueexit()
para relatar o erro ao pai.exec()
"./write_file.py". Agora, esse processo não está mais executando nenhum código (a menos que tenhamos falhado em executar; nesse caso,exit()
reportaremos o erro ao pai).wait()
que o filho termine e manipule seu código de saída (copiando-o para$?
, pelo menos).Portanto, o redirecionamento deve ocorrer no filho entre
fork()
andexec()
: ele não pode acontecer antesfork()
porque não deve alterar o stdout do shell e depois nãoexec()
porque o nome do arquivo e o código executável do shell foram substituídos pelo programa Python . O pai não tem acesso aos descritores de arquivo do filho (e, mesmo que tivesse, não poderia garantir o redirecionamento entreexec()
e a primeira gravação no stdout).fonte
Lamento informar que é exatamente o contrário. O shell precisa abrir sua E / S primeiro e depois passar o controle para o programa.
tee
pode ser útil neste caso:./write_file.py | tee -a ~root/log > /dev/null
fonte