Spooler de tarefas:
Faz o truque muito bem. Espero que seja incluído nos repositórios de pacotes do Ubuntu.
Eu quero a capacidade de agendar comandos para serem executados em uma fila FIFO. Eu não quero que eles sejam executados em um horário específico no futuro, como seria o caso do comando "at". Eu quero que eles comecem a correr agora, mas não simultaneamente. O próximo comando agendado na fila deve ser executado somente após o primeiro comando terminar a execução. Alternativamente, seria bom se eu pudesse especificar um número máximo de comandos da fila que poderiam ser executados simultaneamente; por exemplo, se o número máximo de comandos simultâneos for 2, somente no máximo 2 comandos agendados na fila seriam retirados da fila de maneira FIFO a ser executada, o próximo comando na fila restante sendo iniciado somente quando um dos atualmente 2 comandos em execução são concluídos.
Eu ouvi que o spooler de tarefas poderia fazer algo assim, mas este pacote não parece ser bem suportado / testado e não está nos repositórios padrão do Ubuntu (sendo o Ubuntu o que eu estou usando). Se essa é a melhor alternativa, me avise e usarei spooler de tarefas, caso contrário, estou interessado em descobrir qual é a melhor maneira, mais fácil, mais testada, sem erros e canônica de fazer uma coisa dessas com o bash.
ATUALIZAÇÃO:
Soluções simples como; ou & & do bash não funcionam. Eu preciso agendar esses comandos de um programa externo, quando ocorre um evento. Eu só não quero ter centenas de instâncias do meu comando em execução simultaneamente, daí a necessidade de uma fila. Existe um programa externo que acionará eventos onde posso executar meus próprios comandos. Eu quero lidar com todos os eventos disparados, eu não quero perder nenhum evento, mas eu também não quero que meu sistema trave, então é por isso que eu quero uma fila para lidar com os meus comandos disparados do programa externo.
Use ;
Por exemplo: ls ; touch test ; ls
Isso listará o diretório. Somente depois que ls
for executado, ele executará touch test
, o que criará um arquivo chamado test. E somente depois que terminar, o próximo comando será executado. (Nesse caso, outro ls
mostrará o conteúdo antigo e o arquivo recém-criado).
Comandos semelhantes são ||
e &&
.
;
sempre executará o próximo comando.
&&
só executará o próximo comando do primeiro sucesso retornado.
Exemplo: rm -rf *.mp3 && echo "Success! All MP3s deleted!"
||
só executará o próximo comando se o primeiro comando retornar um valor de retorno de falha (diferente de zero).
Exemplo: rm -rf *.mp3 || echo "Error! Some files could not be deleted! Check permissions!"
Se você quiser executar um comando em segundo plano, anexe um e comercial ( &
).
Exemplo: make bzimage &
e mp3blaster sound.mp3
e make mytestsoftware ; ls ; firefox ; make clean
Será executado dois comandos em segundo plano (neste caso, uma compilação do kernel que levará algum tempo e um programa para reproduzir algumas músicas). E nos foregrounds ele roda outro trabalho de compilação e, uma vez terminado, ls, firefox e make clean (todos sequencialmente)
Para mais detalhes, consulte man bash
[Editar após comentário]
no pseudo código, algo assim?
Program run_queue: While(true) { Wait_for_a_signal(); While( queue not empty ) { run next command from the queue. remove this command from the queue. // If commands where added to the queue during execution then // the queue is not empty, keep processing them all. } // Queue is now empty, returning to wait_for_a_signal }
// // Wait forever on commands and add them to a queue // Signal run_quueu when something gets added. // program add_to_queue() { While(true) { Wait_for_event(); Append command to queue signal run_queue } }
A maneira mais fácil seria simplesmente executar os comandos sequencialmente:
cmd1; cmd2; cmd3; cmdN
Se você quiser que o próximo comando execute somente se o comando anterior tiver saído com sucesso, use &&
:
cmd1 && cmd2 && cmd3 && cmdN
Essa é a única forma básica que sei fazer o que você quer. Se você precisar de controle de tarefas (definindo vários trabalhos paralelos, etc.), poderá tentar instalar um gerenciador de filas, como TORQUE mas isso parece um exagero se tudo o que você quer fazer é lançar trabalhos sequencialmente.
Você está procurando o irmão gêmeo de at
: batch
. Ele usa o mesmo daemon, mas em vez de agendar um horário específico, os trabalhos são enfileirados e serão executados sempre que a média de carga do sistema for baixa.
Além dos sistemas de enfileiramento dedicados (como o Sun Grid Engine ) que você também pode usar localmente em uma máquina e que oferecer dezenas de possibilidades, você pode usar algo como
command1 && command2 && command3
qual é o outro extremo - uma abordagem muito simples. Este último não fornece múltiplos processos simultâneos nem o preenchimento gradual da "fila".
Eu fui na mesma rota pesquisando, experimentando o spooler de tarefas e assim por diante. O melhor dos melhores é este:
Paralelo GNU - semáforo - fg Também tem -j para trabalhos paralelos.