web-dev-qa-db-fra.com

Comment obtenir le chemin d'un processus sous Unix/Linux

Dans l'environnement Windows, il existe une API pour obtenir le chemin qui exécute un processus. Y a-t-il quelque chose de similaire sous Unix/Linux?

Ou existe-t-il un autre moyen de le faire dans ces environnements?

112
lsalamon

Sous Linux, le lien symbolique /proc/<pid>/exe a le chemin de l'exécutable. Utilisez la commande readlink -f /proc/<pid>/exe pour obtenir la valeur.

Sous AIX, ce fichier n'existe pas. Vous pouvez comparer cksum <actual path to binary> et cksum /proc/<pid>/object/a.out.

150
jpalecek

Vous pouvez trouver le fichier exe facilement par ces moyens, essayez-le vous-même.

  • ll /proc/<PID>/exe
  • pwdx <PID>
  • lsof -p <PID> | grep cwd
43
hahakubile

Un peu tard, mais toutes les réponses étaient spécifiques à Linux.

Si vous avez aussi besoin d'unix, alors vous avez besoin de ceci:

char * getExecPath (char * path,size_t dest_len, char * argv0)
{
    char * baseName = NULL;
    char * systemPath = NULL;
    char * candidateDir = NULL;

    /* the easiest case: we are in linux */
    size_t buff_len;
    if (buff_len = readlink ("/proc/self/exe", path, dest_len - 1) != -1)
    {
        path [buff_len] = '\0';
        dirname (path);
        strcat  (path, "/");
        return path;
    }

    /* Ups... not in linux, no  guarantee */

    /* check if we have something like execve("foobar", NULL, NULL) */
    if (argv0 == NULL)
    {
        /* we surrender and give current path instead */
        if (getcwd (path, dest_len) == NULL) return NULL;
        strcat  (path, "/");
        return path;
    }


    /* argv[0] */
    /* if dest_len < PATH_MAX may cause buffer overflow */
    if ((realpath (argv0, path)) && (!access (path, F_OK)))
    {
        dirname (path);
        strcat  (path, "/");
        return path;
    }

    /* Current path */
    baseName = basename (argv0);
    if (getcwd (path, dest_len - strlen (baseName) - 1) == NULL)
        return NULL;

    strcat (path, "/");
    strcat (path, baseName);
    if (access (path, F_OK) == 0)
    {
        dirname (path);
        strcat  (path, "/");
        return path;
    }

    /* Try the PATH. */
    systemPath = getenv ("PATH");
    if (systemPath != NULL)
    {
        dest_len--;
        systemPath = strdup (systemPath);
        for (candidateDir = strtok (systemPath, ":"); candidateDir != NULL; candidateDir = strtok (NULL, ":"))
        {
            strncpy (path, candidateDir, dest_len);
            strncat (path, "/", dest_len);
            strncat (path, baseName, dest_len);

            if (access(path, F_OK) == 0)
            {
                free (systemPath);
                dirname (path);
                strcat  (path, "/");
                return path;
            }
        }
        free(systemPath);
        dest_len++;
    }

    /* again someone has use execve: we dont knowe the executable name; we surrender and give instead current path */
    if (getcwd (path, dest_len - 1) == NULL) return NULL;
    strcat  (path, "/");
    return path;
}

EDITED: Correction du bug signalé par Mark lakata.

27
Hiperion

J'utilise:

ps -ef | grep 786

Remplacez 786 par votre PID ou nom de processus.

11
User

pwdx <process id>

Cette commande va chercher le chemin du processus à partir duquel il s'exécute.

5
gobi

Sous Linux, chaque processus a son propre dossier dans /proc. Vous pouvez donc utiliser getpid() pour obtenir le pid du processus en cours, puis le joindre au chemin /proc pour obtenir le dossier dont vous avez besoin, espérons-le.

Voici un court exemple en Python:

import os
print os.path.join('/proc', str(os.getpid()))

Voici l'exemple en ANSI C:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>


int
main(int argc, char **argv)
{
    pid_t pid = getpid();

    fprintf(stdout, "Path to current process: '/proc/%d/'\n", (int)pid);

    return EXIT_SUCCESS;
}

Compilez-le avec:

gcc -Wall -Werror -g -ansi -pedantic process_path.c -oprocess_path 
4
hyperboreean

merci : Kiwy
avec AIX:

getPathByPid()
{
    if [[ -e /proc/$1/object/a.out ]]; then
        inode=`ls -i /proc/$1/object/a.out 2>/dev/null | awk '{print $1}'`
        if [[ $? -eq 0 ]]; then
            strnode=${inode}"$"
            strNum=`ls -li /proc/$1/object/ 2>/dev/null | grep $strnode | awk '{print $NF}' | grep "[0-9]\{1,\}\.[0-9]\{1,\}\."`
            if [[ $? -eq 0 ]]; then
                # jfs2.10.6.5869
                n1=`echo $strNum|awk -F"." '{print $2}'`
                n2=`echo $strNum|awk -F"." '{print $3}'`
                # brw-rw----    1 root     system       10,  6 Aug 23 2013  hd9var
                strexp="^b.*"$n1,"[[:space:]]\{1,\}"$n2"[[:space:]]\{1,\}.*$"   # "^b.*10, \{1,\}5 \{1,\}.*$"
                strdf=`ls -l /dev/ | grep $strexp | awk '{print $NF}'`
                if [[ $? -eq 0 ]]; then
                    strMpath=`df | grep $strdf | awk '{print $NF}'`
                    if [[ $? -eq 0 ]]; then
                        find $strMpath -inum $inode 2>/dev/null
                        if [[ $? -eq 0 ]]; then
                            return 0
                        fi
                    fi
                fi
            fi
        fi
    fi
    return 1
}
2
zirong

Il n'y a pas de méthode "garantie de travailler n'importe où".

L'étape 1 consiste à vérifier argv [0], si le programme a été démarré par son chemin complet, cela aurait (généralement) le chemin complet. Si elle a été démarrée par un chemin relatif, la même chose est valable (bien que cela nécessite l’obtention du répertoire de travail actuel, en utilisant getcwd ().

L'étape 2, si rien de ce qui précède ne se vérifie, consiste à obtenir le nom du programme, puis le nom du programme à partir de argv [0], puis le PATH de l'utilisateur à partir de l'environnement et examinez-le pour voir s'il existe un correctif. exécutable binaire avec le même nom.

Notez que argv [0] est défini par le processus qui exécute le programme, il n'est donc pas fiable à 100%.

2
Vatine

Vous pouvez également obtenir le chemin sur GNU/Linux avec (non complètement testé):

char file[32];
char buf[64];
pid_t pid = getpid();
sprintf(file, "/proc/%i/cmdline", pid);
FILE *f = fopen(file, "r");
fgets(buf, 64, f);
fclose(f);

Si vous voulez le répertoire de l'exécutable pour éventuellement changer le répertoire de travail en répertoire du processus (pour media/data/etc), vous devez tout supprimer après le dernier /:

*strrchr(buf, '/') = '\0';
/*chdir(buf);*/
1
Jimmio92

La commande ci-dessous recherche le nom du processus dans la liste des processus en cours et redirige la commande pid en pwdx afin de localiser l'emplacement du processus.

ps -ef | grep "abc" |grep -v grep| awk '{print $2}' | xargs pwdx

Remplacez "abc" par votre motif spécifique.

Sinon, si vous pouvez le configurer comme une fonction dans .bashrc, vous pourrez le trouver plus pratique si vous avez besoin de l’utiliser fréquemment.

ps1() { ps -ef | grep "$1" |grep -v grep| awk '{print $2}' | xargs pwdx; }

Par exemple:

[admin@myserver:/home2/Avro/AvroGen]$ ps1 nifi

18404: /home2/Avro/NIFI

J'espère que cela aide quelqu'un parfois .....

0
Arun