¿Cómo hacer pasar los argumentos de la línea de comandos a un proceso en ejecución en sistemas unix / linux?

203

En SunOS hay un pargscomando que imprime los argumentos de la línea de comando pasados ​​al proceso en ejecución.

¿Hay algún comando similar en otros entornos Unix?

Hemant
fuente
44
tr \\0 ' ' < /proc/<pid>/cmdline
Dmitry Grigoryev

Respuestas:

307

Hay varias opciones:

ps -fp <pid>
cat /proc/<pid>/cmdline | sed -e "s/\x00/ /g"; echo

Hay más información en /proc/<pid> sobre Linux, solo eche un vistazo.

En otros Unixes las cosas pueden ser diferentes. El pscomando funcionará en todas partes, el /procmaterial es específico del sistema operativo. Por ejemplo, en AIX no hay cmdlineen /proc.

markus_b
fuente
49
En Linux, probablemente necesitará -ww (es decir ps -ww -fp <pid>) para especificar una salida amplia, ya que si hay varios comandos, podrían cortarse.
Silfheed
2
La -wwopción permite el acceso a argumentos completos de la línea de comandos (tanto como sea almacenado por el núcleo). Vea también: cómo solaris y bsd obtienen los parámetros de línea de comandos no truncados para un proceso y opciones ps
GuruM
3
cat /proc/<pid>/cmdlinetambién funciona en Cygwin, donde los argumentos de línea cmd no se muestran pscon ninguna opción.
lechup
3
En Linux, si solo necesita obtener el args, el comando es ps -o args -p <pid>y solo imprimirá argso usará -o cmdsi solo necesita ver el cmd. Intentar leer /proc/<pid>/cmdlineno siempre funcionará para usuarios sin privilegios. La psutilidad funcionará.
Alvits
2
Sugerencia: la longitud de /proc/<pid>/cmdlinees limitada (codificada al valor del parámetro de kernel PAGE_SIZE), por lo que las líneas de comando más largas aún se muestran truncadas. Consulte stackoverflow.com/questions/199130/… para obtener más información. Puede consultar la configuración de su núcleo getconf PAGE_SIZE, generalmente es 4096.
t0r0X
61

Esto hará el truco:

xargs -0 < /proc/<pid>/cmdline

Sin los xargs, no habrá espacios entre los argumentos, ya que se han convertido a NUL.

Michael Böckling
fuente
3
Esto se puede acortar a xargs -0 < /proc/<pid>/cmdline.
slm
Todavía está truncando mi salida. ¿Algún consejo?
johnsam
Nunca noté ningún truncamiento, ¿puede dar un ejemplo?
Michael Böckling
De esta manera, no puede decir si es un espacio en línea o un límite de argumento.
ivan_pozdeev
19

Línea de comando completa

Para Linux y Unix System puedes usar ps -ef | grep process_name para obtener la línea de comando completa.

En los sistemas SunOS, si desea obtener la línea de comando completa, puede usar

/usr/ucb/ps -auxww | grep -i process_name

Para obtener la línea de comando completa, debe convertirse en súper usuario.

Lista de argumentos

pargs -a PROCESS_ID

dará una lista detallada de argumentos pasados ​​a un proceso. Producirá la matriz de argumentos de esta manera:

argv[o]: first argument
argv[1]: second..
argv[*]: and so on..

No encontré ningún comando similar para Linux, pero usaría el siguiente comando para obtener una salida similar:

tr '\0' '\n' < /proc/<pid>/environ
LOGAN
fuente
14

En Linux

cat /proc/<pid>/cmdline

obtiene la línea de comando del proceso (incluidos los argumentos) pero con todos los espacios en blanco cambiados a caracteres NUL.

lothar
fuente
3
El espacio en blanco no se elimina, se reemplaza con NUL.
bdonlan 05 de
@bdonlan Ah, no lo comprobé. ¡Buena atrapada!
lothar
44
xargs -0 echo </ proc / <pid> / cmdline. También puede hacer esto con / proc / <pid> / environment también, aunque es posible que desee agregar -n 1 para eso.
camh
En mi sistema no hay un sistema de archivos / proc :( ¿alguna otra solución?
Hemant
El mío es un proceso de Java con parámetros largos largos largos. Todavía está truncando mi salida. ¿Algún consejo?
johnsam
14

Puede usar pgrepcon -f(línea de comando completa) y -l(descripción larga):

pgrep -l -f PatternOfProcess

Este método tiene una diferencia crucial con cualquiera de las otras respuestas: funciona en CygWin , por lo que puede usarlo para obtener la línea de comando completa de cualquier proceso que se ejecute en Windows (ejecutar como elevado si desea datos sobre cualquier proceso elevado / administrador) . Cualquier otro método para hacer esto en Windows es más incómodo ( por ejemplo ).
Además: en mis pruebas, la forma pgrep ha sido el único sistema que funcionó para obtener la ruta completa para los scripts que se ejecutan dentro de Python de CygWin .

Sopalajo de Arrierez
fuente
En realidad, este también imprime el nombre del ejecutable original:$ exec -a fakename bash & [1] 14102 [1]+ Stopped exec -a fakename bash $ xargs -0 < /proc/14102/cmdline; fakename $ pgrep -l -f fakename; 14102 bash
unhammer
No funciona para mí usando pgrep from procps-ng 3.3.15y 3.3.12. Simplemente imprime el nombre pid y prorgam sin argumentos.
Socowi
4

Otra variante de impresión /proc/PID/cmdlinecon espacios en Linux es:

cat -v /proc/PID/cmdline | sed 's/\^@/\ /g' && echo

De esta forma catimprime caracteres NULL como ^@y luego los reemplaza con un espacio usando sed; echoImprime una nueva línea.

Diego
fuente
Para su información, también puede usar cat -v / proc / PID / cmdline | sed 's / \ ^ @ / \ n / g' . Esto reemplazará el carácter nulo con un carácter de nueva línea. Al hacerlo, cada argumento se imprimirá en su propia línea. De esa manera, es más fácil distinguir un argumento de otro.
TSJNachos117
2

Simplemente puede usar:

ps -o args= -f -p ProcessPid
Mitar
fuente
2

En lugar de usar múltiples comandos para editar la secuencia, solo use one - tr traduce un carácter a otro:

tr '\0' ' ' </proc/<pid>/cmdline
Tom Evans
fuente
1

Además de todas las formas anteriores para convertir el texto, si simplemente usa 'cadenas', hará que la salida en líneas separadas de forma predeterminada. Con el beneficio adicional de que también puede evitar que aparezcan caracteres que codifiquen su terminal.

Ambos resultados en un solo comando:

cadenas / proc // cmdline / proc // ambient

La verdadera pregunta es ... ¿hay alguna manera de ver la línea de comando real de un proceso en Linux que ha sido alterado de modo que la línea de cm contiene el texto alterado en lugar del comando real que se ejecutó?

Timothy J. Biggs
fuente
1

En Solaris

     ps -eo pid,comm

similar puede usarse en sistemas similares a Unix.

HuntM
fuente
1

En Linux, con bash, para generar los argumentos entre comillas para que pueda editar el comando y volver a ejecutarlo

</proc/"${pid}"/cmdline xargs --no-run-if-empty -0 -n1 \
    bash -c 'printf "%q " "${1}"' /dev/null; echo

En Solaris, con bash (probado con 3.2.51 (1) -release) y sin gnu userland:

IFS=$'\002' tmpargs=( $( pargs "${pid}" \
    | /usr/bin/sed -n 's/^argv\[[0-9]\{1,\}\]: //gp' \
    | tr '\n' '\002' ) )
for tmparg in "${tmpargs[@]}"; do
    printf "%q " "$( echo -e "${tmparg}" )"
done; echo

Ejemplo de bash de Linux (pegar en la terminal):

{
## setup intial args
argv=( /bin/bash -c '{ /usr/bin/sleep 10; echo; }' /dev/null 'BEGIN {system("sleep 2")}' "this is" \
    "some" "args "$'\n'" that" $'\000' $'\002' "need" "quot"$'\t'"ing" )

## run in background
"${argv[@]}" &

## recover into eval string that assigns it to argv_recovered
eval_me=$(
    printf "argv_recovered=( "
    </proc/"${!}"/cmdline xargs --no-run-if-empty -0 -n1 \
        bash -c 'printf "%q " "${1}"' /dev/null
    printf " )\n"
)

## do eval
eval "${eval_me}"

## verify match
if [ "$( declare -p argv )" == "$( declare -p argv_recovered | sed 's/argv_recovered/argv/' )" ];
then
    echo MATCH
else
    echo NO MATCH
fi
}

Salida:

MATCH

Ejemplo de Solaris Bash:

{
## setup intial args
argv=( /bin/bash -c '{ /usr/bin/sleep 10; echo; }' /dev/null 'BEGIN {system("sleep 2")}' "this is" \
    "some" "args "$'\n'" that" $'\000' $'\002' "need" "quot"$'\t'"ing" )

## run in background
"${argv[@]}" &
pargs "${!}"
ps -fp "${!}"

declare -p tmpargs
eval_me=$(
    printf "argv_recovered=( "
    IFS=$'\002' tmpargs=( $( pargs "${!}" \
        | /usr/bin/sed -n 's/^argv\[[0-9]\{1,\}\]: //gp' \
        | tr '\n' '\002' ) )
    for tmparg in "${tmpargs[@]}"; do
        printf "%q " "$( echo -e "${tmparg}" )"
    done; echo
    printf " )\n"
)

## do eval
eval "${eval_me}"


## verify match
if [ "$( declare -p argv )" == "$( declare -p argv_recovered | sed 's/argv_recovered/argv/' )" ];
then
    echo MATCH
else
    echo NO MATCH
fi
}

Salida:

MATCH
Iwan Aucamp
fuente
0

Si desea obtener el mayor tiempo posible (no estoy seguro de qué límites hay), similar a los pargs de Solaris , puede usar esto en Linux y OSX:

ps -ww -o pid,command [-p <pid> ... ]
pourhaus
fuente
-1

tratar ps -n en una terminal de Linux. Esto mostrará:

1.Todos los procesos EN EJECUCIÓN , su línea de comando y sus PID

  1. El programa inicia los procesos.

Después sabrás qué proceso matar

repzero
fuente