Shell Script se auto-controlando caso tenha sido carregado em background. Uma POG [RESOLVIDO]

1. Shell Script se auto-controlando caso tenha sido carregado em background. Uma POG [RESOLVIDO]

Geraldo Albuquerque
AprendiNoLinux

(usa Ubuntu)

Enviado em 15/04/2012 - 15:34h

Existe uma forma melhor de fazer o teste se o próprio foi lançado em background ?

- Já tentei com jobs. Nada retorna. Nem mesmo passando o número do pid que está em ação.
- Já derrapei usando a variável $! que promete avisar se está rodando em background. Realmente ela até avisa, mas somente na área interativa. Dentro do script não consegui capturar.
Script foi cortado para não enviar pontos que não interessam.


#!/bin/bash
# file: gerador_de_tarefas.sh
# name: Gerador de tarefas para dataware
# Author: Ga_Tux aprendiz de Shell Script
# charset UTF-8
# endofline Linux
# since 2012-04-15 13:13 (GMT -03:00)
# license Não tenho a menor ideia.
# system GNU bash
# version: alfa 0.1
# more: Script vai tentar jogar 250 forks em background.
# objetives: Ficar monitorando a execução dos Scripts em background.
#-----------------------------------------------------------------------------#
#set -x # Liga Debug de tudo.
#trap read DEBUG # Debugando tudo.
# Quando rodar em background deve desabilitar o debug.

# Estratégia - Saber se estou trabalhando em background para inibir mensagens,
# DEBUG e outros malandros.

#-----------------------------------------------------------------------------#
MeuPid="$$" # Pegando meu pid atual.
MeuScript=$(basename "$0") # Pego o nome do meu script.
#-----------------------------------------------------------------------------#
# Ficou um pouco complexo por não saber fazer de outra forma.
# O comando ps mostra todos processos em andamento.
# Usando o número do pid localizo o script que está sendo executado.
# Para o resultado do ps uso fgrep pesquisar "S " porque em bg
# não fica com S+
# O sed vai montar o nome do job para confirmar.
#-----------------------------------------------------------------------------#

MeuJob=$(ps h -j $MeuPid | fgrep "S " | sed 's/.*\/// ; s/ .*//')

echo $MeuPid # Avisando o bestão o que vem por aqui.
echo $MeuJob # Outro aviso ao bestão.

if [ "${MeuScript}" == "${MeuJob}" ] ; then
echo "está dizendo que FOI iniciado em bg"
StartedProcessBG="1"
echo "Meu job $MeuJob " # Só para o bestão confirmar.
else
echo "Meu job $MeuJob " # Olha seu nó cego tá certo.
StartedProcessBG="0"
echo "está dizendo que está vazia. Não iniciado em bg "
fi
sleep 50
echo fim
exit 0



Embora tenha feito várias pesquisas e li com atenção este artigo: http://www.vivaolinux.com.br/artigo/Processos-no-Linux?pagina=6 , não encontrei uma forma melhor de fazer o que pretendo. Da forma que fiz parece ser mais um POG. Se existe outra forma mais limpa de fazer este procedimento alguém me avisa ?

A chamada é feita assim:
$ ./gerador_de_tarefas.sh &

Tente outra vez.......





  


2. MELHOR RESPOSTA

Vinicius Miqueloti
Miqueloti

(usa Lubuntu)

Enviado em 16/04/2012 - 14:53h

Aprendi no linux, utilizando o ps, o campo STAT da para identificar os processos que estão em foreground (eles possuem um + do lado);

Veja o que vc pode diagnosticar utilizando as informações da coluna STAT:

PROCESS STATE CODES
Here are the different values that the s, stat and state output specifiers
(header "STAT" or "S") will display to describe the state of a process.
D Uninterruptible sleep (usually IO)
R Running or runnable (on run queue)
S Interruptible sleep (waiting for an event to complete)
T Stopped, either by a job control signal or because it is being traced.
W paging (not valid since the 2.6.xx kernel)
X dead (should never be seen)
Z Defunct ("zombie") process, terminated but not reaped by its parent.

For BSD formats and when the stat keyword is used, additional characters may
be displayed:
< high-priority (not nice to other users)
N low-priority (nice to other users)
L has pages locked into memory (for real-time and custom IO)
s is a session leader
l is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
+ is in the foreground process group

Com base nesta informação, basta você utilizar ps com awk ou cut para obter a informação da coluna STAT, e se não possuir o caractere + junto com o STATE de seu script, significa que seu processo está em background, dai é só você executar as ações cabíveis para seu script neste caso.

3. Re: Shell Script se auto-controlando caso tenha sido carregado em background. Uma POG [RESOLVIDO]

Geraldo Albuquerque
AprendiNoLinux

(usa Ubuntu)

Enviado em 15/04/2012 - 23:49h

up no malandro ;) Ainda não achei outra solução.


4. Re: Shell Script se auto-controlando caso tenha sido carregado em background. Uma POG [RESOLVIDO]

Sandro Marcell
SMarcell

(usa Slackware)

Enviado em 16/04/2012 - 12:50h

Todos os processos do sistema criam em '/proc' um diretório com o pid do processo em questão, então basta verificar se tal diretório existe.


if [ -d /proc/$! ]; then
echo 'Processo em background'
fi





5. Re: Shell Script se auto-controlando caso tenha sido carregado em background. Uma POG [RESOLVIDO]

Geraldo Albuquerque
AprendiNoLinux

(usa Ubuntu)

Enviado em 16/04/2012 - 13:49h

SMarcell escreveu:

Todos os processos do sistema criam em '/proc' um diretório com o pid do processo em questão, então basta verificar se tal diretório existe.


if [ -d /proc/$! ]; then
echo 'Processo em background'
fi




Vou conferir agora mesmo ;)






6. Re: Shell Script se auto-controlando caso tenha sido carregado em background. Uma POG [RESOLVIDO]

Geraldo Albuquerque
AprendiNoLinux

(usa Ubuntu)

Enviado em 16/04/2012 - 14:22h

SMarcell escreveu:

Todos os processos do sistema criam em '/proc' um diretório com o pid do processo em questão, então basta verificar se tal diretório existe.


if [ -d /proc/$! ]; then
echo 'Processo em background'
fi




Posso estar comendo bola, mas não achei uma diferença que aponte quem está em bg e quem não está.


background
dr-xr-xr-x 2 gatux geraldo 0 2012-04-16 13:32 attr
-rw-r--r-- 1 gatux geraldo 0 2012-04-16 13:32 autogroup
-r-------- 1 gatux geraldo 0 2012-04-16 13:32 auxv
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 cgroup
--w------- 1 gatux geraldo 0 2012-04-16 13:32 clear_refs
-r--r--r-- 1 gatux geraldo 0 2012-04-16 05:15 cmdline
-rw-r--r-- 1 gatux geraldo 0 2012-04-16 13:32 comm
-rw-r--r-- 1 gatux geraldo 0 2012-04-16 13:32 coredump_filter
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 cpuset
lrwxrwxrwx 1 gatux geraldo 0 2012-04-16 13:32 cwd -> /home/administrador/scripts
-r-------- 1 gatux geraldo 0 2012-04-16 13:32 environ
lrwxrwxrwx 1 gatux geraldo 0 2012-04-16 07:44 exe -> /bin/bash
dr-x------ 2 gatux geraldo 0 2012-04-16 05:15 fd
dr-x------ 2 gatux geraldo 0 2012-04-16 13:32 fdinfo
-r-------- 1 gatux geraldo 0 2012-04-16 13:32 io
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 latency
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 limits
-rw-r--r-- 1 gatux geraldo 0 2012-04-16 13:32 loginuid
-r--r--r-- 1 gatux geraldo 0 2012-04-16 07:45 maps
-rw------- 1 gatux geraldo 0 2012-04-16 13:32 mem
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 mountinfo
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 mounts
-r-------- 1 gatux geraldo 0 2012-04-16 13:32 mountstats
dr-xr-xr-x 5 gatux geraldo 0 2012-04-16 13:32 net
dr-x--x--x 2 gatux geraldo 0 2012-04-16 13:32 ns
-rw-r--r-- 1 gatux geraldo 0 2012-04-16 13:32 oom_adj
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 oom_score
-rw-r--r-- 1 gatux geraldo 0 2012-04-16 13:32 oom_score_adj
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 pagemap
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 personality
lrwxrwxrwx 1 gatux geraldo 0 2012-04-16 13:32 root -> /
-rw-r--r-- 1 gatux geraldo 0 2012-04-16 13:32 sched
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 schedstat
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 seccomp_filter
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 sessionid
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 smaps
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 stack
-r--r--r-- 1 gatux geraldo 0 2012-04-16 05:15 stat
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 statm
-r--r--r-- 1 gatux geraldo 0 2012-04-16 05:15 status
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 syscall
dr-xr-xr-x 3 gatux geraldo 0 2012-04-16 13:32 task
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:32 wchan



não está em background
dr-xr-xr-x 2 gatux geraldo 0 2012-04-16 13:37 attr
-rw-r--r-- 1 gatux geraldo 0 2012-04-16 13:37 autogroup
-r-------- 1 gatux geraldo 0 2012-04-16 13:37 auxv
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 cgroup
--w------- 1 gatux geraldo 0 2012-04-16 13:37 clear_refs
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:36 cmdline
-rw-r--r-- 1 gatux geraldo 0 2012-04-16 13:37 comm
-rw-r--r-- 1 gatux geraldo 0 2012-04-16 13:37 coredump_filter
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 cpuset
lrwxrwxrwx 1 gatux geraldo 0 2012-04-16 13:37 cwd -> /home/administrador/scripts
-r-------- 1 gatux geraldo 0 2012-04-16 13:37 environ
lrwxrwxrwx 1 gatux geraldo 0 2012-04-16 13:37 exe -> /bin/bash
dr-x------ 2 gatux geraldo 0 2012-04-16 13:36 fd
dr-x------ 2 gatux geraldo 0 2012-04-16 13:37 fdinfo
-r-------- 1 gatux geraldo 0 2012-04-16 13:37 io
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 latency
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 limits
-rw-r--r-- 1 gatux geraldo 0 2012-04-16 13:37 loginuid
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 maps
-rw------- 1 gatux geraldo 0 2012-04-16 13:37 mem
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 mountinfo
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 mounts
-r-------- 1 gatux geraldo 0 2012-04-16 13:37 mountstats
dr-xr-xr-x 5 gatux geraldo 0 2012-04-16 13:37 net
dr-x--x--x 2 gatux geraldo 0 2012-04-16 13:37 ns
-rw-r--r-- 1 gatux geraldo 0 2012-04-16 13:37 oom_adj
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 oom_score
-rw-r--r-- 1 gatux geraldo 0 2012-04-16 13:37 oom_score_adj
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 pagemap
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 personality
lrwxrwxrwx 1 gatux geraldo 0 2012-04-16 13:37 root -> /
-rw-r--r-- 1 gatux geraldo 0 2012-04-16 13:37 sched
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 schedstat
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 seccomp_filter
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 sessionid
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 smaps
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 stack
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:36 stat
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 statm
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:36 status
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 syscall
dr-xr-xr-x 3 gatux geraldo 0 2012-04-16 13:37 task
-r--r--r-- 1 gatux geraldo 0 2012-04-16 13:37 wchan


Se comi bola, me avise. Se tivesse um item dentro das pastas dos processos que indicasse que está em bg resolveria o problema com certeza. Acho que a saída está por analisar o proc mesmo, mas não consegui saber como.

ps: Todos sh que estão em memória tem dentro do diretório proc um PID correspondente. Independe se estão ou não em background.





7. Re: Shell Script se auto-controlando caso tenha sido carregado em background. Uma POG [RESOLVIDO]

Geraldo Albuquerque
AprendiNoLinux

(usa Ubuntu)

Enviado em 16/04/2012 - 14:36h

Olá SMarcell, acho que percebeu a POG temporária que fiz para contornar o problema.


MeuJob=$(ps h -j $MeuPid | fgrep "S " | sed 's/.*\/// ; s/ .*//')


Usando o comando ps identifiquei que uma coluna tinha uma diferença entre "S " quando em bg e com "S+" se não estiver. Mas acho que esta alternativa é frágil. Quando você falou sobre o diretório proc, imaginava que dando um ls -l em todos os arquivos que tem dentro de um determinado PID que uma diferença iria identificar sem sombra de dúvidas quem é bg e quem não é. Talvez seja em outro local do system. Não entendo nada das gravações e nunca me aventurei por estes diretórios. Mas estou desconfiado que a saída ideal ainda é verificar mesmo arquivos no proc ou similares.

Continuo batendo lata tentando achar uma saída mais limpa do que esta que achei.



8. Re: Shell Script se auto-controlando caso tenha sido carregado em background. Uma POG [RESOLVIDO]

Geraldo Albuquerque
AprendiNoLinux

(usa Ubuntu)

Enviado em 16/04/2012 - 15:32h

Miqueloti escreveu:

Aprendi no linux, utilizando o ps, o campo STAT da para identificar os processos que estão em foreground (eles possuem um + do lado);

Veja o que vc pode diagnosticar utilizando as informações da coluna STAT:

PROCESS STATE CODES
Here are the different values that the s, stat and state output specifiers
(header "STAT" or "S") will display to describe the state of a process.
D Uninterruptible sleep (usually IO)
R Running or runnable (on run queue)
S Interruptible sleep (waiting for an event to complete)
T Stopped, either by a job control signal or because it is being traced.
W paging (not valid since the 2.6.xx kernel)
X dead (should never be seen)
Z Defunct ("zombie") process, terminated but not reaped by its parent.

For BSD formats and when the stat keyword is used, additional characters may
be displayed:
< high-priority (not nice to other users)
N low-priority (nice to other users)
L has pages locked into memory (for real-time and custom IO)
s is a session leader
l is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
+ is in the foreground process group

Com base nesta informação, basta você utilizar ps com awk ou cut para obter a informação da coluna STAT, e se não possuir o caractere + junto com o STATE de seu script, significa que seu processo está em background, dai é só você executar as ações cabíveis para seu script neste caso.


Olá Miqueloti. Valeu pelas observações e dicas. Então sem querer já estou mais ou menos fazendo isso porque filtro justamente a coluna STAT, só que de maneira bem porquinha rrss.
Vou rever o código:

MeuJob=$(ps h -j $MeuPid | fgrep "S " | sed 's/.*\/// ; s/ .*//')


Vou forçar ele atuar exclusivamente na coluna do STAT. Valeu mesmo·


9. Re: Shell Script se auto-controlando caso tenha sido carregado em background. Uma POG [RESOLVIDO]

Geraldo Albuquerque
AprendiNoLinux

(usa Ubuntu)

Enviado em 16/04/2012 - 18:36h

Olá SMarcell, marquei a melhor resposta ao Miqueloti porque acho que a alternativa agora parece funcionar bem. Caso encontre algo melhor avise aí :)

Quem desejar testar é só copiar o trecho de código e salvar o danado.
Script de exemplo para testar a nova função.


#!/bin/bash
# file: gerador_de_tarefas.sh
# name: Gerador de tarefas para dataware
# Author: Ga_Tux aprendiz de Shell Script
# charset UTF-8
# endofline Linux
# since 2012-04-16 15:40 (GMT -03:00)
# license Não tenho a menor ideia.
# system GNU bash
# version: alfa 0.2
# more: Script vai tentar jogar 250 forks em background.
# objetives: Ficar monitorando a execução dos Scripts em background.
#-----------------------------------------------------------------------------#
# XXX: Indique detalhes importantes em locais do código como alerta.
# FIXME: Mostre pontos onde você sabe que tem problemas e precisa de ajustes.
# TODO: Faça anotações sobre o que precisa ser feito no ponto. Features.
# ----------------------------------------------------------------------------#
# CHANGELOG: Versão alfa 0.2 - 2012-04-16 15:40
# --------------------------
# - Transformado teste se é foreground em função.
# ----------------------------------------------------------------------------#
# CHANGELOG: Versão alfa 0.1 - 2012-04-15 13:13
# ---------------------------------------------
# - Criação básica de script para testes.
# ----------------------------------------------------------------------------#
#set -x # Liga Debug de tudo.
#trap read DEBUG # Debugando tudo.
# Quando rodar em background deve desabilitar o debug.
# Estratégia - Saber se estou trabalhando em background para inibir mensagens,
# DEBUG e outros malandros.
# ----------------------------------------------------------------------------#

#-----------------------------------------------------------------------------#
# FUNÇÃO: is_foreground()
# Objetivo: Receber o número de um PID e retorna se está em foreground ou bg.
# PARÂMETROS:
# 1 - Número do PID
# Aplicação: De uso geral, Genérica lib.
#-----------------------------------------------------------------------------#
function is_foreground()
{
local lc_mypid lc_retorno lc_myjob lc_jobfound

# Uma proteção para o caso de não passar um número como PID.
lc_mypid=$(if [[ $1 = ?(+|-)+([0-9]) ]]; then echo $1; else echo 0; fi)
if [ $((lc_mypid)) -eq 0 ]; then
lc_retorno="3" # PID INFORMADO NÃO ESTAVA NOS PROCESSOS.
return 0
fi
lc_jobfound=$(ps h -j $((lc_mypid)) | awk '{ printf "%s ", $2}')
if [ $((lc_mypid)) -eq $((lc_jobfound)) ]; then
lc_myjob=$(ps h -j $((lc_mypid)) | awk '{ printf "%s ", $5}')
if [ "${lc_myjob}" == "S+ " ]; then
lc_retorno="0"
else
lc_retorno="1"
fi
else
lc_retorno="2" # PID INFORMADO NÃO ESTAVA NOS PROCESSOS.
fi
echo $lc_retorno
return 0
}
#-----------------------------------------------------------------------------#
# FUNÇÃO: is_foreground()
#-----------------------------------------------------------------------------#
# RETORNA: 1 Número.
# ForeGround = 0 (verdadeiro)
# BackGround = 1 (falso) mas confirmado que está em BackGround
# NotFound = 2 (Não achou job em andamento)
# ErroPID = 3 (Erro no nº do PID. Não era numérico)
#-----------------------------------------------------------------------------#

c=0
s=0

# Loop infinito para confirmar se teste da função será válido.
# Na utilização real posso passar qualquer PID para o teste da função.
while true ; do 2>/dev/null
sleep 1
c=$((c+1))
if [ "$c" -gt 1 ]; then
s=$((s+1))
retorno_func=$(is_foreground "$$")
if [ "${retorno_func}" == "2" ]; then
echo "Script do PID:$$ NÃO FOI está ENCONTRADO"
else
if [ "${retorno_func}" == "1" ]; then
echo "Script do PID:$$ está operando em BACKGROUND"
else
echo "Script do PID:$$ está operando em FOREGROUND"
fi
fi
else
echo "Contado ainda não atingiu o número necessário para o teste"
fi
if [ "$s" -gt 7 ]; then
break
fi
done
exit 1


Tem uma pegadinha no código. Quem descobrir ganha uma canção di grátis no youtube rsrs

Passa a régua e vamos para a próxima.





10. Re: Shell Script se auto-controlando caso tenha sido carregado em background. Uma POG [RESOLVIDO]

Geraldo Albuquerque
AprendiNoLinux

(usa Ubuntu)

Enviado em 09/05/2012 - 20:58h

SMarcell escreveu:

Todos os processos do sistema criam em '/proc' um diretório com o pid do processo em questão, então basta verificar se tal diretório existe.


if [ -d /proc/$! ]; then
echo 'Processo em background'
fi




A minha função não está trabalhando legal. A sua dica @SMarcell sempre retorna background.
Por ora estou contornando assim:


function is_foreground()
{
local lc_myprogbg="$1" lc_retorno
lc_jobfound=$(ps h -j | \
grep $lc_myprogbg | \
grep -v grep | \
awk '{ printf "%s ", $5}')

if [ "${lc_jobfound}" == "S S " -o "${lc_jobfound}" == "S S S " ]; then
lc_retorno="is_BackGround"
else
Debug 1 "Trabalhando e ForeGround. [F:$FUNCNAME L:$LINENO]"
lc_retorno="is_ForeGround"
fi
BG_RETURN=${lc_retorno}
echo $BG_RETURN

return 0
}


O problema é que geralmente tenho mais de 3 forks de uma aplicação, ex:
Rotina que chama outra rotina, que chama outra rotina, etc...

Claro que se o primeiro retorna bg os outros tem que ser também. A função acima falha porque ainda não encontrei uma forma melhor de fazer.
A função usa como base a dica do @Miqueloti






11. Re: Shell Script se auto-controlando caso tenha sido carregado em background. Uma POG [RESOLVIDO]

Geraldo Albuquerque
AprendiNoLinux

(usa Ubuntu)

Enviado em 21/05/2012 - 23:16h

A função só funciona se o 1º Script que for chamar os outros em bg também for iniciado da mesma forma.
Se o 1º for chamado de forma normal, a função não conseguirá recuperar o flag.
Escolhi uma opção mais simples que é ao chamar qualquer script em bg pegar o pid dele e gerar um arquivo. O script não sabe que foi chamado em bg sou eu que passo o parâmetro que diz ser bg. Aí gero um arquivo físico que se existir sei que está em background.

Qualquer outra alternativa é bemvinda. Está funcionando bem desta forma mas sei que é uma POG lascada.







Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts