Comment faire passer les arguments de ligne de commande à un processus en cours d'exécution sur les systèmes Unix / Linux?

203

Sous SunOS, il existe une pargscommande qui imprime les arguments de ligne de commande passés au processus en cours d'exécution.

Existe-t-il une commande similaire sur d'autres environnements Unix?

Hemant
la source
4
tr \\0 ' ' < /proc/<pid>/cmdline
Dmitry Grigoryev

Réponses:

307

Il existe plusieurs options:

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

Il y a plus d'informations /proc/<pid>sur Linux, jetez un œil.

Sur d'autres Unix, les choses pourraient être différentes. La pscommande fonctionnera partout, le /proctruc est spécifique au système d'exploitation. Par exemple, sous AIX, il n'y a pas d' cmdlineentrée /proc.

markus_b
la source
49
sous linux, vous aurez probablement besoin de -ww (ie ps -ww -fp <pid>) pour spécifier une sortie large car s'il y a plusieurs commandes, elles pourraient être coupées.
Silfheed
2
l' -wwoption permet d'accéder aux arguments de ligne de commande complets (autant que ceux stockés par le noyau). Voir aussi: comment solaris et bsd obtiennent les paramètres de ligne de commande non tronqués pour un processus et des options ps
GuruM
3
cat /proc/<pid>/cmdlinefonctionne également sur Cygwin, où les arguments de ligne cmd ne sont affichés psavec aucune option.
lechup
3
Sous Linux, si vous avez seulement besoin d'obtenir le args, la commande est ps -o args -p <pid>et elle n'imprimera le argsou n'utilisera -o que cmdsi vous avez seulement besoin de voir le cmd. Essayer de lire /proc/<pid>/cmdlinene fonctionnera pas toujours pour les utilisateurs sans privilège. L' psutilitaire fonctionnera.
alvits
2
Astuce: la longueur de /proc/<pid>/cmdlineest limitée (codée en dur à la valeur du paramètre du noyau PAGE_SIZE), donc les lignes de commande plus longues sont toujours affichées tronquées! Voir stackoverflow.com/questions/199130/… pour plus d'informations. Vous pouvez interroger votre paramètre de noyau avec getconf PAGE_SIZE, c'est généralement 4096.
t0r0X
61

Ça fera l'affaire:

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

Sans les xargs, il n'y aura pas d'espaces entre les arguments, car ils ont été convertis en NUL.

Michael Böckling
la source
3
Cela peut être raccourci xargs -0 < /proc/<pid>/cmdline.
slm
C'est encore tronquer ma sortie. Un conseil?
johnsam
Je n'ai jamais remarqué de troncature - pouvez-vous donner un exemple?
Michael Böckling
De cette façon, vous ne pouvez pas dire s'il s'agit d'un espace en ligne ou d'une limite d'argument.
ivan_pozdeev
19

Ligne de commande complète

Pour les systèmes Linux et Unix, vous pouvez utiliser ps -ef | grep process_namepour obtenir la ligne de commande complète.

Sur les systèmes SunOS, si vous souhaitez obtenir la ligne de commande complète, vous pouvez utiliser

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

Pour obtenir la ligne de commande complète, vous devez devenir super utilisateur.

Liste des arguments

pargs -a PROCESS_ID

donnera une liste détaillée des arguments passés à un processus. Il affichera le tableau d'arguments comme ceci:

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

Je n'ai trouvé aucune commande similaire pour Linux, mais j'utiliserais la commande suivante pour obtenir une sortie similaire:

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

Sous Linux

cat /proc/<pid>/cmdline

vous obtenez la ligne de commande du processus (y compris les arguments) mais avec tous les espaces blancs modifiés en caractères NUL.

lothar
la source
3
L'espace n'est pas supprimé, il est remplacé par des NUL.
bdonlan
@bdonlan Ah, je n'ai pas vérifié cela. Bonne prise!
lothar
4
xargs -0 echo </ proc / <pid> / cmdline. Vous pouvez également le faire avec / proc / <pid> / environ, bien que vous souhaitiez peut-être ajouter -n 1 pour cela.
camh
Sur mon système, il n'y a pas de système de fichiers / proc :( toute autre solution?
Hemant
Le mien est un processus java avec des paramètres long long long. C'est encore tronquer ma sortie. Un conseil?
johnsam
14

Vous pouvez utiliser pgrepavec -f(ligne de commande complète) et -l(description longue):

pgrep -l -f PatternOfProcess

Cette méthode a une différence cruciale avec toutes les autres réponses: elle fonctionne sur CygWin , vous pouvez donc l'utiliser pour obtenir la ligne de commande complète de tout processus exécuté sous Windows (exécutez comme élevé si vous voulez des données sur tout processus élevé / administrateur) . Toute autre méthode pour le faire sous Windows est plus gênante ( par exemple ).
De plus: dans mes tests, la méthode pgrep a été le seul système qui a fonctionné pour obtenir le chemin complet pour les scripts s'exécutant dans le python de CygWin .

Sopalajo de Arrierez
la source
Celui-ci imprime également le nom de l'exécutable d'origine:$ 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
Ne fonctionne pas pour moi en utilisant pgrep from procps-ng 3.3.15et 3.3.12. Imprime simplement le nom pid et prorgam sans arguments.
Socowi
4

Une autre variante de l'impression /proc/PID/cmdlineavec des espaces sous Linux est:

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

De cette façon, catimprime les caractères NULL en tant que ^@, puis vous les remplacez par un espace utilisant sed; echoimprime une nouvelle ligne.

Diego
la source
Pour info, vous pouvez également utiliser cat -v / proc / PID / cmdline | sed 's / \ ^ @ / \ n / g' . Cela remplacera le caractère nul par un caractère de nouvelle ligne. Ce faisant, chaque argument sera imprimé sur sa propre ligne. De cette façon, il est plus facile de distinguer un argument d'un autre.
TSJNachos117
2

Vous pouvez simplement utiliser:

ps -o args= -f -p ProcessPid
Mitar
la source
2

Plutôt que d'utiliser plusieurs commandes pour éditer le flux, utilisez simplement one - tr traduit un caractère en un autre:

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

En plus de toutes les façons ci-dessus pour convertir le texte, si vous utilisez simplement des "chaînes", cela produira la sortie sur des lignes séparées par défaut. Avec l'avantage supplémentaire, cela peut également empêcher l'apparition de caractères susceptibles de brouiller votre terminal.

Les deux sorties en une seule commande:

chaînes / proc // cmdline / proc // environ

La vraie question est ... existe-t-il un moyen de voir la vraie ligne de commande d'un processus sous Linux qui a été modifié de sorte que la cmdline contienne le texte modifié au lieu de la commande réelle qui a été exécutée.

Timothy J. Biggs
la source
1

Sur Solaris

     ps -eo pid,comm

similaire peut être utilisé sur des systèmes de type Unix.

HuntM
la source
1

Sous Linux, avec bash, pour afficher les arguments entre guillemets afin que vous puissiez modifier la commande et la réexécuter

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

Sous Solaris, avec bash (testé avec la version 3.2.51 (1)) et sans espace utilisateur gnu:

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

Exemple de bash Linux (coller dans le 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
}

Production:

MATCH

Exemple 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
}

Production:

MATCH
Iwan Aucamp
la source
0

Si vous souhaitez obtenir un délai aussi long que possible (vous ne savez pas quelles sont les limites), similaire aux paramètres de Solaris , vous pouvez l'utiliser sur Linux et OSX:

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

essayez ps -ndans un terminal linux. Cela montrera:

1.Tous les processus RUNNING , leur ligne de commande et leurs PID

  1. Le programme initie les processus.

Ensuite, vous saurez quel processus tuer

repzero
la source