Execução atrasada mais rápida que 1 minuto?

1

Estou trabalhando em um programa que pode "atualizar-se" instalando um novo pacote. Para conseguir isso, estou usando o comando at para especificar que um script de shell deve ser executado em um minuto no futuro e o shell script, por sua vez, instalará o pacote. Eu realmente gostaria que isso fosse executado antes de um minuto no futuro, mas isso parece ser o melhor que posso fazer com base no que eu li na página do manual em. Existe uma maneira de fazer isso com uma resolução mais apertada?

    
por Jon Trauntvein 09.06.2011 / 17:30

4 respostas

3

Seria mais fácil simplesmente iniciar o programa diretamente e executá-lo imediatamente (ou ele poderia dormir por algum pequeno atraso se você realmente precisasse).

Se isso estiver em um script (por exemplo, bash), simplesmente chame o script de atualização diretamente (provavelmente redirecionando a saída):

update-my-thingy < /dev/null > /dev/null 2>&1

Se estiver em um programa, você sempre pode usar a chamada system () para fazer a mesma coisa:

system("update-my-thingy < /dev/null > /dev/null 2>&1");
    
por 09.06.2011 / 18:27
2

Bifurque um script que aguarde alguns segundos.

{ sleep 5; update-my-program; } &

Se o seu objetivo é fazer a atualização assim que o programa for encerrado, mas assim que o programa terminar, chamando execve em vez de exit . A chamada do sistema execve substitui o programa atual por outro. Em C, existem várias variantes ( execl , execp , etc.) dependendo de como você deseja passar parâmetros. No shell, o built-in correspondente é exec .

    
por 09.06.2011 / 23:26
1

Isso depende do que você está programando. Para daemons, é feito da seguinte maneira:

  • determine a idade do executável
  • se a idade for menor que o início do programa, o executável foi substituído por uma nova versão
  • Nesse caso, espere até que não haja trabalho a ser feito (ou não)
  • exec() on self para reiniciar o programa com um novo binário
por 09.06.2011 / 18:48
0

Isso é complicado. Primeiro, apenas por precaução, coloque a chamada em uma função no início do script e não a chame até o final:

% killmenow() { ... }
...
% killmenow
EOF

Esta é a melhor maneira de ter certeza de que tudo a partir do script atual foi totalmente lido e copiado para a memória. Apenas dizendo.

Agora, para minha tentativa de resposta ...

POSIX especifica os utilitários jobs para esses tipos de coisas. Especificamente, uma combinação de wait , trap e kill seria mais segura, eu acho. Para que as coisas estejam se movendo da maneira mais limpa possível, você também pode usar newgrp , que é muito parecido com exec em qualidades de herança, exceto, como poderia ser fundamental neste caso, process id .

Ok, então sei que parece muito, mas depois de tudo não é para olhar:

% suicide() { _me="${1}" ; ( 
>> trap 'wait "${_me}" && set -- &&\
>>> eval 'newgrp && exec { YOUR | CMD | HERE }'' INT &&\
>> kill -s INT "-${_me}"
>> ) & }
...
% suicide "${$}"

Ok, então aqui está o fluxo de trabalho:

  • First we load and run the entire script and we're sure of this because we don't suicide until the very last line.
  • We pass to suicide a copy of our process id then save it to $_me, which we could just as easily get from within suicide as well in this case, but we might use it elsewhere, who knows.
  • From within a subshell we call trap to scan in its trapped '$cmd' and instruct it to be on the lookout for any rumor of an INT call.
  • Sure all is ready, our call to kill is our very last; kill issues an INTERRUPT SIGNAL not only to $_me but we - specify that $_my process whole group should receive it. Have no fear - unless your whole system is already insane - $_me can't kill anything $_me shouldnt be able to right now anyway. Also, you dont have to - specify that in kill's PID argument either; I'm just trying to be thorough.

Ok, mas não terminamos, certo? Não, colocamos todo o conjunto de comandos em uma subshell & backgrounded, então trap ainda está por perto e podemos capturar nossa chamada INT .

  • Having recieved its INT, trap NOW evaluates its 'quoted argument' - it's important to remember that anything within this string is only now being pulled out.
  • Just in case $_me has a few other loose ends to tie up elsewhere, trap first calls wait on $_me which will hold the line only for as long as it must.
  • When ready, we scrub any remaining env $vars with set -- and then we get down to business.

newgrp foi projetado para ser executado em interactive shell - não é necessariamente necessário fornecer um processo tão limpo como este. Na verdade, se o group do seu sistema exigir senhas - o que elas não deveriam - isso não funcionará para você e morrerá agora.

Eu chamo esse método sorrateiro abaixo, mas eu o retirei diretamente das orientações do POSIX:

A common implementation of newgrp is that the current shell uses exec to overlay itself with newgrp, which in turn overlays itself with a new shell after changing group...

Então, no próximo parágrafo ...

The newgrp command is intended only for use from an interactive terminal. It does not offer a useful interface for the support of applications.

Assim, a parte sorrateira é eval , o que pode ser muito bom nesse tipo de coisa - como salvar e reutilizar "$@" , por exemplo, mas em outra ocasião, talvez ...

  • Instead, we indirectly eval a newgrp && exec statement that first loads another process that is only supposed to take its next command from an interactive prompt, then we sneakily exec in the back door the contents of { YOUR | CMD }.

A essa altura, deveríamos estar executando um novo script em um novo shell em um novo grupo de processos em um ambiente limpo, depois de ter que esperar apenas o tempo que fosse necessário e ter retirado a coisa toda bem.

Na verdade, éramos tão meticulosos que poderíamos fazer isso com segurança:

...exec { wget -O - "${URL}" >"${0}" ; exec "${0}" }
    
por 30.11.2013 / 00:46