Eu tenho um pequeno script, que é chamado diariamente pelo crontab usando o seguinte comando:
/homedir/MyScript &> some_log.log
O problema com esse método é que some_log.log só é criado depois que o MyScript termina. Eu gostaria de liberar a saída do programa no arquivo enquanto ele está sendo executado para que eu pudesse fazer coisas como
tail -f some_log.log
e acompanhar o progresso, etc.
sys.stdout.flush()
.Respostas:
O próprio bash nunca gravará nenhuma saída em seu arquivo de log. Em vez disso, os comandos que ele invoca como parte do script irão, cada um individualmente, gravar a saída e liberar sempre que desejar. Portanto, a sua pergunta é realmente como forçar o esvaziamento dos comandos dentro do script bash, e isso depende do que eles são.
fonte
Eu encontrei uma solução para isso aqui . Usando o exemplo do OP, você basicamente executa
e o buffer é liberado após cada linha de saída. Costumo combinar isso com
nohup
a execução de trabalhos longos em uma máquina remota.Desta forma, o seu processo não é cancelado quando você sai.
fonte
stdbuf
? Com base neste comentário , parece que não está disponível em algumas distros. Você poderia esclarecer?stdbuf
é parte do GNU coreutils, a documentação pode ser encontrada em gnu.orgexport -f my_function
estdbuf -oL bash -c "my_function -args"
se precisar executar uma função em vez de um scriptA chave é -f. Citação do man script:
-f, --flush Flush output after each write. This is nice for telecooperation: one person does 'mkfifo foo; script -f foo', and another can supervise real-time what is being done using 'cat foo'.
Executado em segundo plano:
fonte
busybox
! (minha concha congela depois, mas tanto faz)Você pode usar
tee
para gravar no arquivo sem a necessidade de descarregar.fonte
Isso não é uma função de
bash
, pois tudo o que o shell faz é abrir o arquivo em questão e, em seguida, passar o descritor de arquivo como a saída padrão do script. O que você precisa fazer é garantir que a saída seja eliminada do seu script com mais frequência do que você atualmente.Em Perl, por exemplo, isso pode ser feito definindo:
Veja perlvar para mais informações sobre isso.
fonte
O armazenamento em buffer da saída depende de como seu programa
/homedir/MyScript
é implementado. Se você descobrir que a saída está sendo armazenada em buffer, será necessário forçá-la em sua implementação. Por exemplo, use sys.stdout.flush () se for um programa Python ou use fflush (stdout) se for um programa C.fonte
Isso ajudaria?
tail -f access.log | stdbuf -oL cut -d ' ' -f1 | uniq
Isso exibirá imediatamente entradas exclusivas do access.log usando o utilitário stdbuf .
fonte
stdbuf
disponível no Ubuntu no momento, não tenho certeza de onde consegui.stdbuf
faz parte decoreutilus
(encontrado comapt-file search /usr/bin/stdbuf
).O problema aqui é que você tem que esperar que os programas que você executa a partir do seu script terminem seus trabalhos.
Se no seu script você executa o programa em segundo plano, você pode tentar algo mais.
Em geral, uma chamada para
sync
antes de sair permite liberar buffers do sistema de arquivos e pode ajudar um pouco.Se no script você iniciar alguns programas em segundo plano (
&
), você pode esperar que eles terminem antes de sair do script. Para se ter uma ideia de como ele pode funcionar você pode ver abaixo#!/bin/bash #... some stuffs ... program_1 & # here you start a program 1 in background PID_PROGRAM_1=${!} # here you remember its PID #... some other stuffs ... program_2 & # here you start a program 2 in background wait ${!} # You wait it finish not really useful here #... some other stuffs ... daemon_1 & # We will not wait it will finish program_3 & # here you start a program 1 in background PID_PROGRAM_3=${!} # here you remember its PID #... last other stuffs ... sync wait $PID_PROGRAM_1 wait $PID_PROGRAM_3 # program 2 is just ended # ...
Uma vez que
wait
funciona com tarefas e também comPID
números, uma solução preguiçosa deve ser colocada no final do scriptfor job in `jobs -p` do wait $job done
Mais difícil é a situação se você executar algo que executa outra coisa em segundo plano porque você tem que pesquisar e esperar (se for o caso) o fim de todo o processo filho : por exemplo, se você executar um daemon provavelmente não é o caso esperar termine :-).
Nota:
wait $ {!} significa "esperar até que o último processo em segundo plano seja concluído" onde
$!
está o PID do último processo em segundo plano. Então, colocarwait ${!}
logo depoisprogram_2 &
é equivalente a executar diretamenteprogram_2
sem enviá-lo em segundo plano com&
Com a ajuda de
wait
:Syntax wait [n ...] Key n A process ID or a job specification
fonte
Obrigado
@user3258569
, o script é talvez a única coisa que funcionabusybox
!A casca estava congelando para mim depois disso, no entanto. Procurando a causa, encontrei estes grandes avisos vermelhos "não use em shells não interativos" na página de manual do script :
Verdadeiro.
script -c "make_hay" -f /dev/null | grep "needle"
estava congelando a casca para mim.Camponês ao aviso, pensei que
echo "make_hay" | script
IRÁ passar um EOF, por isso tenteiecho "make_hay; exit" | script -f /dev/null | grep 'needle'
e funcionou!
Observe os avisos na página do manual. Isso pode não funcionar para você.
fonte
alternativa para stdbuf é
awk '{print} END {fflush()}'
eu gostaria que houvesse um bash embutido para fazer isso. Normalmente não deveria ser necessário, mas com versões mais antigas pode haver erros de sincronização do bash nos descritores de arquivo.fonte
Não sei se daria certo, mas que tal ligar
sync
?fonte
sync
é uma operação de sistema de arquivos de baixo nível e não está relacionada à saída em buffer no nível do aplicativo.sync
grava quaisquer buffers de sistema de arquivos sujos no armazenamento físico, se necessário. Isso é interno ao sistema operacional; os aplicativos executados no sistema operacional sempre têm uma visão coerente do sistema de arquivos, independentemente de os blocos de disco terem sido gravados ou não no armazenamento físico. Para a pergunta original, o aplicativo (script) provavelmente está armazenando em buffer a saída em um buffer interno ao aplicativo, e o SO nem saberá (ainda) que a saída está realmente destinada a ser gravada em stdout. Portanto, uma operação hipotética do tipo "sincronização" não seria capaz de "acessar" o script e extrair os dados.Tive esse problema com um processo em segundo plano no Mac OS X usando o
StartupItems
. É assim que eu resolvo:Se eu fizer
sudo ps aux
, posso ver quemytool
foi lançado.Descobri que (devido ao buffer), quando o Mac OS X é encerrado,
mytool
nunca transfere a saída para osed
comando. No entanto, se eu executarsudo killall mytool
,mytool
transfere a saída para osed
comando. Portanto, adicionei umstop
caso aoStartupItems
que é executado quando o Mac OS X é encerrado:start) if [ -x /sw/sbin/mytool ]; then # run the daemon ConsoleMessage "Starting mytool" (mytool | sed .... >> myfile.txt) & fi ;; stop) ConsoleMessage "Killing mytool" killall mytool ;;
fonte
bem, goste ou não, é assim que o redirecionamento funciona.
No seu caso, a saída (significando que o seu script foi concluído) do seu script redirecionada para esse arquivo.
O que você deseja fazer é adicionar esses redirecionamentos em seu script.
fonte