agendar tarefas em segundo plano em sucessão

2

Eu tenho três programas SAS para rodar em segundo plano em um final de semana. Os três programas geram informações em arquivos com os mesmos nomes, portanto, eu precisarei remover esses arquivos de saída depois que o primeiro programa terminar e antes do início do segundo programa, bem como após o término do segundo programa e antes do início do terceiro programa. Obviamente, a maneira mais simples de contornar esse problema é alterar cada um dos programas de forma que os nomes dos arquivos de saída sejam diferentes, mas isso não me ajudaria a aprender como usar o Unix. Então é isso que eu tenho até agora:

# Begin by running the first SAS program in the background.
sas program1.sas & | at 5:00 PM JAN 11

# I'd like to wait until the first program finishes to remove
# the output files and run the second program.
wait ???
rm file1.sas7bdat file2.sas7bdat file3.sas7bdat file4.sas7bdat file5.sas7bdat
sas program2.sas & | at 5:00 PM JAN 12

# And now I repeat.
wait ???
rm file1.sas7bdat file2.sas7bdat file3.sas7bdat file4.sas7bdat file5.sas7bdat
sas program3.sas & | at 5:00 PM JAN 13

Eu configurei cada programa para ser executado ao mesmo tempo em dias consecutivos por dois motivos: (1) Eu sei que o programa anterior terminará dentro de 24 horas, e (2) estou supondo que a carga no servidor será similar em ao mesmo tempo em dias consecutivos. Idealmente eu poderia de alguma forma pegar o ID do processo para o primeiro programa e passá-lo para o primeiro comando wait , e similarmente para o segundo programa e o comando wait . Alguma idéia?

EDITAR

Estou mais interessado em uma solução geral para determinar um ID de processo e transmiti-lo ao comando wait do que essa situação específica.

    
por Max 10.01.2013 / 21:20

3 respostas

5

O problema é que você está usando algo que não deveria ser usado, na verdade. Você também tem dois objetivos conflitantes: "executar o programa 2 após o programa 1" e "executar o programa 2 às 17h de 12 de janeiro".

Uma parte do seu problema é simples de resolver: at permite vários comandos. Portanto, em vez de usar apenas at para agendar o script sas , você também pode colocar o rm no trabalho.

at 5:00 PM JAN 11 <<EOJ
sas program1.sas
rm file1.sas7bdat file2.sas7bdat file3.sas7bdat file4.sas7bdat file5.sas7bdat
EOJ

Não há motivo para o & na linha sas ; at sempre executa trabalhos "em segundo plano".

Em seguida, você deve descobrir como deseja resolver o conflito mencionado anteriormente. Em particular, se o trabalho de 11 de janeiro não tiver terminado 24 horas depois (até as 17h de 12 de janeiro). Existem algumas maneiras de fazer isso:

  • Não é realmente o trabalho de 12 de janeiro. Deve ser executado assim que o programa1.sas terminar. Nesse caso, faça parte do primeiro trabalho acima, assim como o rm .
  • Isso nunca acontecerá. Em caso afirmativo, você irá corrigi-lo manualmente. Nesse caso, basta agendá-lo como o acima.
  • Precisa esperar. Nesse caso, você pode programá-lo no final do primeiro no trabalho, ou usar um arquivo de bloqueio ou calcular a quantidade adequada de tempo para dormir (ou usar sleepenh , se disponível, para evitar fazer o cálculo) .
por 10.01.2013 / 22:08
2

Então o que você tem e quer fazer basicamente se resume ao seguinte.

command1 &
wait <on command1>
sleep <until specified time>

command2 &
wait <on command2>
sleep <until specified time>

...

Nesse caso, remover o fundo ( & ) e também o wait e sleep farão com que os comandos sejam executados em seqüência. Isso, no entanto, fará com que eles executem imediatamente após o outro.

Para esperar até uma hora específica, você pode sleep pelo período de tempo adequado. sleep leva alguns segundos como entrada, e os sistemas Unix tradicionalmente mantêm e medem o tempo em segundos, então isso se resume a simples aritmética:

  1. Converta a data e a hora de espera em segundos desde a época.
  2. Converta o tempo atual em segundos desde a época.
  3. Calcule a diferença.
  4. Durma por tanto tempo.

Como fazer isso é muito bem apresentado em esta resposta de estouro de pilha , mas para copiar a parte essencial:

current_epoch=$(date +%s)
target_epoch=$(date -d '01/01/2010 12:00' +%s)
sleep_seconds=$(( $target_epoch - $current_epoch ))
sleep $sleep_seconds

Esse exemplo específico é a sintaxe bash, mas deve ser fácil convertê-lo em praticamente qualquer linguagem de script shell. $(...) executa um comando e substitui pela saída desse comando e $(( ... )) avalia uma expressão aritmética.

O GNU date -d também suporta carimbos de data e hora, portanto você pode dizer date -d '05:00' e isso será traduzido para as próximas 05:00.

Juntando isso, deve ser fácil criar um script como o que você deseja.

    
por 10.01.2013 / 22:07
0

Bem, não há comando wait . Pelo menos não que eu saiba. Aqui está minha lógica alternativa:

Crie 3 arquivos de script para cada programa sas. Estes scripts só serão executados se o programa sas anterior tiver terminado a execução. Isso pode ser feito capturando pid do programa sas anterior e verificando com o comando ps que ele não está mais sendo executado antes de remover os arquivos de saída.

Agende os scripts com crontab para serem executados toda sexta a domingo, respectivamente.

Então, se eu nomeei o primeiro arquivo de script sas_script1.sh , seria assim:

if [ -f /var/run/sas.pid ]; then
    /bin/ps $( cat /var/run/sas.pid ) >/dev/null
    [ $? ] && exit               #  $? checks the exit status of the last command
fi

rm -f /path/to/file{1..5}.sas7bdat

/usr/bin/sas /path/to/program1.sas &

echo $! >/var/run/sas.pid       #  $! gives you the PID of the last program that's sent background

Escreva o mesmo script para o restante dos dois programas sas, por exemplo, edite apenas program1.sas to program2.sas

Crie um file e escreva o seguinte:

00 17 * * 5 /path/to/sas_script1.sh
00 17 * * 6 /path/to/sas_script2.sh
00 17 * * 0 /path/to/sas_script3.sh

Agora, faça o upload do arquivo como trabalho do cron:

crontab /path/to/file

Você pode aprender mais sobre Un * X desta maneira: D

    
por 10.01.2013 / 22:06

Tags