¿Por qué decirme un pid ilegal cuando se elimina el proceso?

¿Por qué decirme un pid ilegal cuando se elimina el proceso?

Ahora estoy usando este script para reiniciar mi proceso:

PID=`ps -ef|grep -w ${APP_NAME}|grep -v grep|cut -c 9-15`
if [[ ${PID} -gt 1 ]]; then
  kill -9 ${PID}
else
  echo "Process not found"
fi

pero cuando ejecuto este script en un servidor remoto desde GitHub Actions, muestra este error:

======CMD======
cd /opt/apps/dolphin-acientbay/libs
. /opt/apps/dolphin-acientbay/libs/upgrade.sh

======END======
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:13> JAVA_HOME=/***/.sdkman/candidates/java/11.0.11.hs-adpt 
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:14> APP_HOME=/opt/apps/dolphin-acientbay/libs 
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:15> APP_NAME=dolphin-acientbay-service-1.0.0-SNAPSHOT.jar 
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> PID=+/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> ps -ef
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> PID=+/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> grep -w dolphin-acientbay-service-1.0.0-SNAPSHOT.jar
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> PID=+/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> grep -v grep
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> PID=+/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> cut -c 9-15
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:17> PID=' 19882 ' 
2021/05/30 11:46:21 Process exited with status 1
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:18> [[ ' 19882 ' -gt 1 ]]
err: +/opt/apps/dolphin-acientbay/libs/upgrade.sh:19> kill -9 ' 19882 '
err: /opt/apps/dolphin-acientbay/libs/upgrade.sh:kill:19: illegal pid:  19882 

este es el guión completo de upgrade.sh:

#!/usr/bin/env bash

set -u

set -e

set -x

JAVA_HOME="/root/.sdkman/candidates/java/11.0.11.hs-adpt"
APP_HOME="/opt/apps/dolphin-acientbay/libs"
APP_NAME="dolphin-acientbay-service-1.0.0-SNAPSHOT.jar"

PID=`ps -ef|grep -w ${APP_NAME}|grep -v grep|cut -c 9-15`
if [[ ${PID} -gt 1 ]]; then
  kill -9 ${PID}
else
  echo "Process not found"
fi

sleep 5

count=`ps -ef | grep ${APP_NAME} | grep -v "grep" | wc -l`
if [[ ${count} -lt 1 ]]; then
  nohup ${JAVA_HOME}/bin/java -Xmx128M -Xms128M -jar \
  -Xdebug -Xrunjdwp:transport=dt_socket,suspend=n,server=y,address=0.0.0.0:5021 \
  -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/apps/dolphin-acientbay/ \
  ${APP_HOME}/${APP_NAME} >> ./acientbay.log &
  sleep 5
else
  echo "process aready exists!"
  exit 1
fi

Intenté modificar el comando del proceso de eliminación de esta manera (los xargs recortan el espacio en blanco de pid) para eliminar los espacios de pid:

 echo "${PID}" | xargs | kill -9

me dice:

err: /opt/apps/dolphin-acientbay/libs/upgrade.sh:kill:19: not enough arguments

Respuesta1

Aquí está la fuente de su problema:

PID=`ps -ef|grep -w ${APP_NAME}|grep -v grep|cut -c 9-15`
  1. Entrecomilla dos veces tus variables cuando las uses. por ejemplo, "$APP_NAME" o "${APP_NAME}".

    Por cierto, las llaves solo son necesarias cuando necesita eliminar la ambigüedad de una variable de otro texto en una cadena. por ejemplo, si la variable fuera realmente $APPpero necesitara usarla en una cadena con _NAME, usaría "${APP}_NAME"- eso evitaría _NAMEque el shell la interprete como parte del nombre de la variable.

  2. Estás usando comillas invertidas en lugar de $(). Han estado en desuso durante años y por una buena razón. No son la causa del problema aquí, sólo un mal hábito que debes dejar.

  3. cutno es una buena herramienta para extraer campos que puedan estar delimitados por 1 o más caracteres. Sólo es bueno cuando hay un (y exactamente uno) delimitador entre campos. Muchos archivos de texto utilizan 1 o más espacios (y/o tabulaciones y/u otros caracteres de espacios en blanco) como delimitadores de campo y no se pueden procesar fácilmente con cut. Utilice awko perlen su lugar.

    Su uso de cut -c 9-15está provocando que se capture al menos un carácter de espacio adicional en $PID. Para extraer un PID de ps -ef, utilice awk '{print $2}'en lugar de cut -c 9-15.

  4. Úselo pgrep "$APP_NAME"para obtener el PID de un proceso por nombre. O pgrep -f "$APP_NAME"si la cadena que está buscando es un argumento (por ejemplo, cuando el nombre del script se pasa como argumento a un intérprete).

    El culto a la carga ps | grep ... | grep -v grepha quedado obsoleto desde hace décadas y, de todos modos, nunca fue una buena forma de hacerlo. ps -ef | awk '/[p]rocess_name/ {print $2}'Siempre fue una mejor manera (poner un []alrededor del primer carácter del patrón evita que awk, grep o lo que sea coincida en la salida de ps), pero incluso eso ahora está obsoleto con pgrep.

    psen sí mismo tiene una -Copción para hacer coincidir nombres de procesos y una hopción para suprimir encabezados y -oespecificar de qué salida desea ps. p.ejps h -o pid -C "$APP_NAME"

Para resumir todo eso, use:

    PID=$(pgrep "$APP_NAME")
or
    PID=$(pgrep -f "$APP_NAME")
or
    PID=$(ps h -o pid -C "$APP_NAME")

Por cierto, si haycualquierpgrepposibilidad de que o devuelva múltiples PID ps, debe capturar la salida en una matriz, no en una variable escalar. Por ejemplo, lo siguiente capturará los PID de todos los procesos bash visibles en la matriz $BASHPIDS.

$ BASHPIDS=( $(ps h -o pid -C bash) )

$ typeset -p BASHPIDS
declare -a BASHPIDS=([0]="68910" [1]="71059" [2]="71634" [3]="71641" [4]="71643"
[5]="71680" [6]="71683" [7]="71684" [8]="71687" [9]="71693" [10]="71712" [11]="72394"
[12]="72568" [13]="72589" [14]="970222" [15]="974740" [16]="1078757" [17]="1278073"
[18]="1365082" [19]="1405642" [20]="1458889" [21]="2278763" [22]="2466442" [23]="2876831"
[24]="2955565" [25]="3260896" [26]="3261235" [27]="3269020" [28]="3281961" [29]="3702104" 
[30]="4038149")

Si, por alguna razón, quisieras matarlos a todos, podrías hacerlo con:

kill "${BASHPIDS[@]}"

Respuesta2

este comando soluciona el problema:

 echo "${PID}" | xargs kill -9

información relacionada