Como posso acordar um script bash?

26

É possível ativar um processo que é pausado usando o comando sleep ?

Como exemplo, digamos que você tenha este script:

#!/bin/bash
echo "I am tired"
sleep 8h
echo "I am fresh :)"

Após 30 minutos, você descobre que precisa parar com o script, ou seja, desejou ter escrito sleep 30m .

Você não quer chamar kill PID ou pressionar Ctrl + C , desde então o último comando não é executado e você permanecerá cansado.

Existe uma maneira de ativar o processo a partir de sleep ou talvez usar outro comando que suporte a ativação? Soluções para processos de fundo e primeiro plano são bem-vindas.

    
por Bittenus 20.01.2015 / 10:32

4 respostas

45

Quando um script de Bash está executando um sleep , veja como o pstree se parece:

bash(10102)───sleep(8506)

Ambos possuem IDs de processo (PIDs), mesmo quando executados como um script. Se quiséssemos interromper o sono, enviaríamos kill 8506 e a sessão de Bash seria retomada ... O problema está em um ambiente de script que não conhecemos o PID do comando sleep e não há um humano para olhar para a árvore de processos.

Podemos obter o PID da sessão de Bash através da variável $$ magic. Se pudermos armazenar isso em algum lugar, poderemos então direcionar instâncias de sleep que estão sendo executadas abaixo desse PID. Aqui está o que eu coloquei no script:

# write the current session's PID to file
echo $$ >> myscript.pid

# go to sleep for a long time
sleep 1000

E então podemos dizer pkill para nuke sleep instâncias sendo executadas abaixo do PID:

pkill -P $(<myscript.pid) sleep

Mais uma vez, isso está se limitando a apenas sleep processos executados diretamente sob essa sessão de Bash. Contanto que o PID tenha sido registrado corretamente, isso torna muito mais seguro que killall sleep ou pkill sleep , o que poderia eliminar qualquer % processo desleep no sistema (permissões permitidas).

Podemos provar essa teoria com o seguinte exemplo, em que temos três sessões bash separadas, duas executando sleep . Somente porque estamos especificando o PID da sessão bash superior esquerda, apenas seu sleep é eliminado.

Uma abordagem alternativa é empurrar sleep para o segundo plano, armazenar seu PID e, em seguida, retorná-lo ao primeiro plano. No script:

sleep 1000 &
echo $! > myscript.sleep.pid
fg

E para matá-lo:

kill $(<myscript.sleep.pid)
    
por Oli 20.01.2015 / 10:46
5

Você poderia escrever seu script para manipular ("trap") outros sinais de kill etc., assim você poderia modificar o comportamento dos scripts conforme necessário. Veja man bash:

SIGNALS
   When  bash  is  interactive,  in the absence of any traps, it ignores SIGTERM (so that kill 0 does not
   kill an interactive shell), and SIGINT is caught and handled (so that the wait builtin  is  interrupt-
   ible).   In all cases, bash ignores SIGQUIT.  If job control is in effect, bash ignores SIGTTIN, SIGT-
   TOU, and SIGTSTP.

   Non-builtin commands run by bash have signal handlers set to the values inherited by  the  shell  from
   its  parent.   When  job  control is not in effect, asynchronous commands ignore SIGINT and SIGQUIT in
   addition to these inherited handlers.  Commands run as a result of  command  substitution  ignore  the
   keyboard-generated job control signals SIGTTIN, SIGTTOU, and SIGTSTP.

   The shell exits by default upon receipt of a SIGHUP.  Before exiting, an interactive shell resends the
   SIGHUP to all jobs, running or stopped.  Stopped jobs are sent SIGCONT to ensure that they receive the
   SIGHUP.   To  prevent the shell from sending the signal to a particular job, it should be removed from
   the jobs table with the disown builtin (see SHELL BUILTIN COMMANDS below) or  marked  to  not  receive
   SIGHUP using disown -h.

   If  the huponexit shell option has been set with shopt, bash sends a SIGHUP to all jobs when an inter-
   active login shell exits.

   If bash is waiting for a command to complete and receives a signal for which a trap has been set,  the
   trap  will not be executed until the command completes.  When bash is waiting for an asynchronous com-
   mand via the wait builtin, the reception of a signal for which a trap has been set will cause the wait
   builtin  to  return immediately with an exit status greater than 128, immediately after which the trap
   is executed.
    
por afbach 20.01.2015 / 19:49
4

Você poderia apenas matar o sono, o que continuaria na próxima linha do script:

pkill sleep

Observe que isso eliminaria qualquer processo de suspensão em execução no sistema, não apenas no script.

    
por animaletdesequia 20.01.2015 / 10:47
1

Eu tenho um script bash para dormir iniciado por cron na inicialização. O script é ativado a cada minuto e define o brilho da tela do laptop com base no nascer e no pôr do sol obtidos da Internet. Uma fase de transição configurável pelo usuário entre full bright e full dim requer aumentar e diminuir os valores em 3, 4, 5 ou o que for calculado a cada minuto.

Oli tocou brevemente em pstree em sua resposta, mas a rejeitou porque isso mataria todos os sleep instâncias. Isso pode ser evitado ao restringir a pesquisa usando as opções do pstree.

Usando pstree -h , vemos toda a hierarquia:

$ pstree -h
systemd─┬─ModemManager─┬─{gdbus}
        │              └─{gmain}
        ├─NetworkManager─┬─dhclient
        │                ├─dnsmasq
        │                ├─{gdbus}
        │                └─{gmain}
        ├─accounts-daemon─┬─{gdbus}
        │                 └─{gmain}
        ├─acpid
        ├─agetty
        ├─atd
        ├─avahi-daemon───avahi-daemon
        ├─cgmanager
        ├─colord─┬─{gdbus}
        │        └─{gmain}
        ├─cron───cron───sh───display-auto-br───sleep
        ├─cups-browsed─┬─{gdbus}
        │              └─{gmain}
        ├─dbus-daemon
        ├─fwupd─┬─3*[{GUsbEventThread}]
        │       ├─{fwupd}
        │       ├─{gdbus}
        │       └─{gmain}
        ├─gnome-keyring-d─┬─{gdbus}
        │                 ├─{gmain}
        │                 └─{timer}
        ├─irqbalance
        ├─lightdm─┬─Xorg───3*[{Xorg}]
        │         ├─lightdm─┬─upstart─┬─at-spi-bus-laun─┬─dbus-daemon
        │         │         │         │                 ├─{dconf worker}
        │         │         │         │                 ├─{gdbus}
        │         │         │         │                 └─{gmain}
        │         │         │         ├─at-spi2-registr─┬─{gdbus}
        │         │         │         │                 └─{gmain}
        │         │         │         ├─bamfdaemon─┬─{dconf worker}
        │         │         │         │            ├─{gdbus}
        │         │         │         │            └─{gmain}
        │         │         │         ├─chrome─┬─2*[cat]
        │         │         │         │        ├─chrome─┬─chrome─┬─2*[chrome─┬─{Chrome_ChildIOT}]
        │         │         │         │        │        │        │           ├─5*[{CompositorTileW}]]
        │         │         │         │        │        │        │           ├─{Compositor}]
        │         │         │         │        │        │        │           ├─{GpuMemoryThread}]
        │         │         │         │        │        │        │           ├─{MemoryInfra}]
        │         │         │         │        │        │        │           ├─{Renderer::FILE}]
        │         │         │         │        │        │        │           ├─{TaskSchedulerRe}]
        │         │         │         │        │        │        │           └─{TaskSchedulerSe}]
        │         │         │         │        │        │        ├─7*[chrome─┬─{Chrome_ChildIOT}]
        │         │         │         │        │        │        │           ├─5*[{CompositorTileW}]]
        │         │         │         │        │        │        │           ├─{Compositor}]
        │         │         │         │        │        │        │           ├─{GpuMemoryThread}]
        │         │         │         │        │        │        │           ├─{MemoryInfra}]
        │         │         │         │        │        │        │           ├─{Renderer::FILE}]
        │         │         │         │        │        │        │           ├─{ScriptStreamerT}]
        │         │         │         │        │        │        │           ├─{TaskSchedulerRe}]
        │         │         │         │        │        │        │           └─{TaskSchedulerSe}]
        │         │         │         │        │        │        ├─chrome─┬─{Chrome_ChildIOT}
        │         │         │         │        │        │        │        ├─5*[{CompositorTileW}]
        │         │         │         │        │        │        │        ├─{Compositor}
        │         │         │         │        │        │        │        ├─{GpuMemoryThread}
        │         │         │         │        │        │        │        ├─{Media}
        │         │         │         │        │        │        │        ├─{MemoryInfra}
        │         │         │         │        │        │        │        ├─{Renderer::FILE}
        │         │         │         │        │        │        │        ├─{ScriptStreamerT}
        │         │         │         │        │        │        │        ├─{TaskSchedulerRe}
        │         │         │         │        │        │        │        └─{TaskSchedulerSe}
        │         │         │         │        │        │        └─2*[chrome─┬─{Chrome_ChildIOT}]
        │         │         │         │        │        │                    ├─5*[{CompositorTileW}]]
        │         │         │         │        │        │                    ├─{Compositor}]
        │         │         │         │        │        │                    ├─{GpuMemoryThread}]
        │         │         │         │        │        │                    ├─{Renderer::FILE}]
        │         │         │         │        │        │                    ├─{ScriptStreamerT}]
        │         │         │         │        │        │                    ├─{TaskSchedulerRe}]
        │         │         │         │        │        │                    └─{TaskSchedulerSe}]
        │         │         │         │        │        └─nacl_helper
        │         │         │         │        ├─chrome─┬─chrome
        │         │         │         │        │        ├─{Chrome_ChildIOT}
        │         │         │         │        │        ├─{MemoryInfra}
        │         │         │         │        │        ├─{TaskSchedulerSe}
        │         │         │         │        │        └─{Watchdog}
        │         │         │         │        ├─{AudioThread}
        │         │         │         │        ├─{BrowserWatchdog}
        │         │         │         │        ├─{Chrome_CacheThr}
        │         │         │         │        ├─{Chrome_DBThread}
        │         │         │         │        ├─{Chrome_FileThre}
        │         │         │         │        ├─{Chrome_FileUser}
        │         │         │         │        ├─{Chrome_HistoryT}
        │         │         │         │        ├─{Chrome_IOThread}
        │         │         │         │        ├─{Chrome_ProcessL}
        │         │         │         │        ├─{Chrome_SyncThre}
        │         │         │         │        ├─{CompositorTileW}
        │         │         │         │        ├─{CrShutdownDetec}
        │         │         │         │        ├─{D-Bus thread}
        │         │         │         │        ├─{Geolocation}
        │         │         │         │        ├─{IndexedDB}
        │         │         │         │        ├─{LevelDBEnv}
        │         │         │         │        ├─{MemoryInfra}
        │         │         │         │        ├─{NetworkChangeNo}
        │         │         │         │        ├─{Networking Priv}
        │         │         │         │        ├─4*[{TaskSchedulerBa}]
        │         │         │         │        ├─6*[{TaskSchedulerFo}]
        │         │         │         │        ├─{TaskSchedulerSe}
        │         │         │         │        ├─{WorkerPool/3166}
        │         │         │         │        ├─{WorkerPool/5824}
        │         │         │         │        ├─{WorkerPool/5898}
        │         │         │         │        ├─{WorkerPool/6601}
        │         │         │         │        ├─{WorkerPool/6603}
        │         │         │         │        ├─{WorkerPool/7313}
        │         │         │         │        ├─{chrome}
        │         │         │         │        ├─{dconf worker}
        │         │         │         │        ├─{extension_crash}
        │         │         │         │        ├─{gdbus}
        │         │         │         │        ├─{gmain}
        │         │         │         │        ├─{gpu-process_cra}
        │         │         │         │        ├─{inotify_reader}
        │         │         │         │        ├─{renderer_crash_}
        │         │         │         │        ├─{sandbox_ipc_thr}
        │         │         │         │        └─{threaded-ml}
        │         │         │         ├─compiz─┬─{dconf worker}
        │         │         │         │        ├─{gdbus}
        │         │         │         │        ├─{gmain}
        │         │         │         │        └─8*[{pool}]
        │         │         │         ├─conky───6*[{conky}]
        │         │         │         ├─2*[dbus-daemon]

( .... many lines deleted to fit in 30k limit .... )

        ├─vnstatd
        ├─whoopsie─┬─{gdbus}
        │          └─{gmain}
        └─wpa_supplicant

Como você pode ver, um login típico do Ubuntu contém muitos PIDs (IDs de processo).

Podemos restringi-lo ao nosso script em execução usando:

$ pstree -g -p | grep display-auto
  |-cron(1198,1198)---cron(1257,1198)---sh(1308,1308)---display-auto-br(1321,1308)---sleep(26552,1308)

Nós vemos:

  • cron iniciou um shell (ID do processo 1308 e ID da sessão 1308)
  • O shell chama nosso programa em execução sob o ID de processo 1321 e o ID de sessão 1308 (correspondendo ao shell)
  • Nosso programa chama sleep na ID do processo 26552 e novamente a ID da sessão 1308

Neste ponto, podemos usar pkill -s 1308 e isso mataria toda a sessão que inclui o shell, nosso programa display-auto-brightness e o comando sleep . Em vez disso, usaremos kill 26552 para apenas matar o comando sleep forçando nosso programa a ativar e ajustar o brilho.

Digitando isso manualmente no terminal, você vê:

───────────────────────────────────────────────────────────────────────────────
[email protected]:~$ pstree -g -p | grep display-auto
             |-cron(1198,1198)---cron(1257,1198)---sh(1308,1308)---display-auto-br(1321,1308)---sleep(32362,1308)
───────────────────────────────────────────────────────────────────────────────
[email protected]:~$ sudo kill 32362
───────────────────────────────────────────────────────────────────────────────
[email protected]:~$ pstree -g -p | grep display-auto
             |-cron(1198,1198)---cron(1257,1198)---sh(1308,1308)---display-auto-br(1321,1308)---sleep(1279,1308)
───────────────────────────────────────────────────────────────────────────────
[email protected]:~$ sudo kill 1279
───────────────────────────────────────────────────────────────────────────────
[email protected]:~$ pstree -g -p | grep display-auto
             |-cron(1198,1198)---cron(1257,1198)---sh(1308,1308)---display-auto-br(1321,1308)---sleep(4440,1308)
───────────────────────────────────────────────────────────────────────────────
[email protected]:~$ 

O próximo passo é fazê-lo quando o laptop acordar da suspensão. Por exemplo, quando a tampa estava fechada, estava completamente escuro e o brilho da tela estava ajustado em "300". Quando a tampa está aberta, a luz do dia e o brilho precisam ser definidos como "2000". É claro que o programa acordaria sozinho em 1 a 59 segundos, mas é mais confortável para o brilho ser definido instantaneamente.

Vou postar o código de suspensão / retomada depois de escrito. Esperemos que este fim de semana.

    
por WinEunuuchs2Unix 23.08.2017 / 03:21