Você precisa de uma maneira de encontrar seus processos que estão sendo executados há algum tempo. Para isso, é útil saber que o parâmetro etime mostra o tempo decorrido desde o início do processo, no formato DD-hh: mm: ss, em que cada parte maior é opcional. Então você pode fazer
ps -U sauer -o etime,pid,command
(no AIX, você pode usar ps -U sauer -o "%t,%p,%c"
)
Você poderia usar um -t $( tty)
no lugar do -U username
para selecionar processos no tty atual (também conhecido como no terminal atual). Isso é o que farei depois. Além disso, observe que fazer -o cmd=
suprime o cabeçalho da coluna, mas significa que você precisa de várias opções -o.
Então, você acaba com ps -t $(tty) -o etime= -o pid= -o command=
para mostrar todos os processos em execução no terminal atual, mostrando as colunas "tempo transcorrido do relógio", "ID do processo" e "comando" e suprimindo os cabeçalhos das colunas.
Agora você precisa obter apenas os que estão sendo executados por mais tempo do que os segundos. Então, você precisa extrair a primeira coluna e converter o tempo em segundos. Que tal um script de shell para fazer isso (ksh / bash):
ps -t $(tty) -o etime= -o pid= -o command= | while read time pid cmd
do
secs=0
while true
do
part=${time##*:}
secs=$(( secs + ${part#0} ))
[[ "$part" != "$time" ]] || break # only had seconds
time=${time%:$part}
part=${time##*:}
secs=$(( secs + (60 * ${part#0}) ))
[[ "$part" != "$time" ]] || break # only had minutes left
time=${time%:$part}
part=${time##*-}
secs=$(( secs + (60 * 60 * ${part#0}) ))
[[ "$part" != "$time" ]] || break # only had hours left
time=${time%-$part} # all that's left are days-hours
secs=$(( secs + (24 * 60 * 60 * time) ))
break
done
echo "Process '$cmd' (pid '$pid') has been up for '$secs' seconds"
done
Algumas coisas podem precisar ser explicadas. O ${part#0}
está lá para que os tempos como "06" segundos sejam convertidos para "6" em vez de serem tratados como octal. Claro, octal 06 e decimal 6 são os mesmos, mas octal 09 não é válido, e shells às vezes reclamam disso.
A outra coisa é que ${var##*:}
avalia para qualquer $ var com a maior cadeia correspondente a "*:" removida da frente (uma #
é a correspondência mais curta e %%
/ %
faz a mesmo do final). Se o padrão não corresponder, ele será avaliado como $var
. Então, tiramos tudo menos os segundos, adicionamos isso a segundos e depois removemos os segundos do final. Se temos coisas sobrando, são minutos. Então, tire os minutos, converta em segundos, adicione ao total, limpe-o do final. E assim por diante.
Tudo bem. De lá, agora você só precisa colocar um #!/bin/ksh
(ou bash, se for necessário) no topo, e você tem um script. Exceto que você também precisa de uma maneira de encontrar apenas os pids que estão sendo executados por mais de X segundos. Que tal um arquivo em / tmp. Vamos usar isso no lugar do comando echo:
if [[ $secs -gt 120 ]]
then
{ cat /tmp/pids.$$; echo "$pid $cmd"; } 2>/dev/null | sort -u > /tmp/pids.$$.tmp
while read p c
do
if ps -p $p >/dev/null 2>&1
then
# put it back in the list
echo "$p $c" > /tmp/pids.$$
else
echo "Command '$c' exited" | mailx -s "exit report" $USER
fi
done < /tmp/pids.$$.tmp
fi
Agora tudo o que você precisa fazer é envolver toda a coisa gigante dentro de um loop while
enquanto verdadeiro Faz # o loop while grande e a instrução if dormir 10 feito
Chame process_monitor.sh
e coloque um process_monitor.sh&
no seu .profile ou .bash_login ou o que for. Ele ficará em segundo plano assistindo a todos os processos naquele terminal e, quando encontrar um que esteja em execução por mais de 120 segundos, ele ficará na lista para assisti-lo e enviará um e-mail quando o processo terminar.
Há coisas que eu provavelmente adicionaria para torná-lo mais bonito, como capturar o sinal EXIT e remover os arquivos temporários quando o script sair, etc. Mas isso é um exercício para você. Espero que isso seja o suficiente para você ficar bem no caminho. :)