Maneira correta e confiável de verificar um processo em execução no AIX 7.1.0 no KornShell

1

Eu tenho tentado obter uma maneira de verificar se um script está sendo executado ou não, porque quero garantir que não haja outras instâncias quando eu executar algo. Até agora, eu tentei com isso:

#! /bin/ksh93

getProcessNum(){
    processNum=$(ps -ef | grep -E "$1" \
        | grep -vE "emacs|vi |ve |grep|ps|tail|tee|runProcess|jlast|tlast|elast" \
        | awk '/'$USER'/ { if($1 == "'$USER'") print $0}' \
        | awk -v myPid=$$ '{if ($3 != myPid) print $0}' \
        | wc -l
    )
}

getProcessNum "myAvoidedScript.k"

if [[ $processNum -gt 1 ]]; then
    echo "There are $processNum instances running. Stopping..."
else
    echo "You can continue"
fi

E eu tenho isso:

ThisProcessID=4063450
myUser  4063450  5636606   0 19:06:48 pts/10  0:00 /bin/ksh93 myAvoidedScript.k
myUser  8978492  5964234   0 19:06:48 pts/10  0:00 /bin/ksh93 myAvoidedScript.k
myUser  3277270  9109712 113 11:07:58  pts/5 70:50 /bin/ksh93 myAvoidedScript.k

Pensei que isso fosse o suficiente para fazer isso, mas há alguns processos que são contados, embora sejam parte do mesmo script. Percebi quando tentei rodar esse script e ele retornou um número maior que 1 mesmo que não tenha nada rodando.

Então eu disse: Talvez se eu tentar eliminar as duplicatas que começaram no exato momento exato, seria o suficiente e eu tentei isso:

#! /bin/ksh93

getProcessNum(){
    processNum=$(ps -ef | grep -E "$1" \
        | grep -vE "emacs|vi |ve |grep|ps|tail|tee|runProcess|jlast|tlast|elast" \
        | awk '/'$USER'/ { if($1 == "'$USER'") print $0}' \
        | awk -v myPid=$$ '{if ($3 != myPid) print $0}' \
        | sort -k 4 | awk '!x[$5]++' | wc -l
    )
}

getProcessNum "myAvoidedScript.k"
if [[ $processNum -gt 1 ]]; then
    echo "There are $processNum instances running. Stopping..."
else
    echo "You can continue"
fi

Às vezes eu recebo o resultado correto, mas alguns outros eu recebo isso

Os PIDs retornados nem sempre são os mesmos que os do PID atual ($$):

ThisProcessID=4063450
myUser  3177476  5964232   0 19:06:49 pts/10  0:00 /bin/ksh93 myAvoidedScript.k
myUser  3277270  9109712 113 11:07:58  pts/5 70:50 /bin/ksh93 myAvoidedScript.k

Quando você executa esse script à beira de um segundo, ele ainda traz duas instâncias desse mesmo script.

ThisProcessID=4063450
myUser  4063450  5636606   0 19:07:48 pts/10  0:00 /bin/ksh93 myAvoidedScript.k
myUser  5177476  5964232   0 19:07:49 pts/10  0:00 /bin/ksh93 myAvoidedScript.k
myUser  3277270  9109712 113 11:07:58  pts/5 70:50 /bin/ksh93 myAvoidedScript.k

Alguém sabe como posso garantir que, não importa quando eu executo esse script, ele apenas traga os processos corretos de maneira confiável?

PS. Eu sei que eu poderia usar um arquivo de sinalização, mas isso significaria alterar muitos scripts.

    
por StrayChild01 14.11.2017 / 00:44

2 respostas

3

Eu não tenho um sistema AIX para testar isso, mas você pode estar vendo filhos do script em execução devido ao uso de um pipeline enquanto faz o ps . Você pode tentar evitar isso executando ps por conta própria e capturando sua saída em um arquivo temporário, ou mais simplesmente uma variável. Você também pode simplificar o grep, awk e wc em um comando awk. Por exemplo,

getProcessNum(){
    procs=$(ps -u "$USER" -f)
    processNum=$(printf '%s\n' "$procs" |
        awk -v myPid="$$" -v name="$1" '
            index($0,"ksh93 " name) != 0 && $2 != myPid {tot++}
            END {print tot}'
    )
}
    
por 14.11.2017 / 10:06
2

Does anyone know how can I ensure that no matter when I run this script it only brings the right processes running on a reliable way?

Você poderia pedir a ps para listar os processos pertencentes ao usuário atual -u $USER e para imprimir seus pids, pids pai e cadeias de comando completas (comando e argumentos) e, em seguida, passá-los para awk para fazer mais verificação. O awk recebe o pid do script atual ( -v me=$1 ) e o nome do processo a ser procurado ( -v procname=$2 ) e, em seguida, é instruído a procurar linhas que correspondam a três requisitos:

  1. onde o pid (coluna 1) é não o pid do script atual e
  2. onde o ppid (coluna 2) é não o pid do script atual e
  3. em que a cadeia do comando corresponde ao argumento fornecido

Se alguma linha corresponder a todos esses dois requisitos, o awk imprimirá o pid; esses pids (se houver) são canalizados por meio de wc -l para contar suas instâncias. Você poderia simplesmente aumentar um contador, mas se quisesse investigar os pids para outros propósitos, isso deixaria uma maneira de recuperá-los.

getProcessNum() {
  ps -u "$USER" -o pid=,ppid=,args= |
  awk -v me="$1" -v procname="$2" \
    '$1 != me && $2 != me && index(substr($0,19,length(procname)), procname) { print $1 }' |
  wc -l
}

A principal diferença em relação a meuh é que pedi a ps para imprimir o pai pids, para que possamos especificamente ignorar quaisquer filhos do script atual; Outra diferença é que eu pesquisei especificamente a string começando na coluna 19 (ignorando o pid e o ppid) e ainda mais limitada ao comprimento do nome do processo, antes de determinar uma correspondência com index . Fiz isso para evitar tantos falsos positivos quanto possível, como o reconhecidamente inventado vi ksh93 myAvoidedScript.k .

Você teria que passar o encantamento exato do script, conforme fornecido por ps -o args , para excluir corretamente essas instâncias - por exemplo, aqui, getProcessNum $$ "/bin/ksh93 myAvoidedScript.k" . Se o script puder ser chamado com parâmetros ( /bin/ksh93 myAvoidedScrip.k foo ) ou opções ( ksh93 -x myAvoidedScript.k ) ou caminhos completos ( /bin/ksh93 /path/to/myAvoidedScript.k ) ou com caminhos de intérprete diferentes ( ./ksh93 myAvoidedScript.k ) ou diretamente ( ./myAvoidedScript.k ), então a verificação falharia.

A menos que você possa garantir a invocação precisa do script, será difícil garantir que apenas uma cópia desse script seja executada por vez.

    
por 14.11.2017 / 19:27