¿Cómo obtengo la ruta de un proceso en Unix / Linux


138

En el entorno de Windows hay una API para obtener la ruta que ejecuta un proceso. ¿Hay algo similar en Unix / Linux?

¿O hay alguna otra forma de hacerlo en estos entornos?

Respuestas:


183

En Linux, el enlace simbólico /proc/<pid>/exetiene la ruta del ejecutable. Use el comando readlink -f /proc/<pid>/exepara obtener el valor.

En AIX, este archivo no existe. Podrías comparar cksum <actual path to binary>y cksum /proc/<pid>/object/a.out.


2
sudoSi la salida está vacía, algunos procesos son creados por otros usuarios del sistema.
Lun4i

63

Puede encontrar el exe fácilmente de esta manera, simplemente pruébelo usted mismo.

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

1
Esto es asombroso Sabía que lo ejecutaba desde una ubicación que tenía el enlace simbólico al ejecutable original (una de las muchas versiones). pwdx <PID>me dio la ubicación del enlace simbólico para que pudiera encontrar los registros y detener el proceso de manera adecuada.
NurShomik

1
llpor lo general es un alias: alias ll='ls -alF'.
Pablo A

1
Los dos últimos (pwdx y lsof) pueden no darle el resultado correcto. La pregunta era sobre la ruta completa al ejecutable. pwdx y lsof le darán cwd del proceso en lugar de la ruta al proceso. Creo que la respuesta de jpalecek es más precisa ya que el solicitante original solicitó la ruta al ejecutable en lugar del enlace suave que describe el ejecutable.
Shimon

28

Un poco tarde, pero todas las respuestas fueron específicas de Linux.

Si también necesita unix, entonces necesita esto:

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

EDITADO: Se corrigió el error reportado por Mark lakata.


Gracias por compartir Hiperion, pero necesitaba especificar un PID y obtener su ruta exe, ¿es posible con este código?
Noitidart

1
@Noitidart - reemplazar "/proc/self/exe"consprintf(foo,"/proc/%d/exe",pid)
Mark Lakata

2
Tenga en cuenta que readlink no termina nulo el resultado, por lo que este código tiene un comportamiento indefinido.
Mark Lakata el

¡Gracias @MarkLakata! :)
Noitidart

Gracias por notar @MarkLakata
Hiperion

14

Yo suelo:

ps -ef | grep 786

Reemplace 786 con su PID o nombre de proceso.


11

pwdx <process id>

Este comando buscará la ruta del proceso desde donde se está ejecutando.


La pregunta es sobre API para obtener información, pero gracias de todos modos.
lsalamon

4

En Linux cada proceso tiene su propia carpeta /proc. Entonces podría usar getpid()para obtener el pid del proceso en ejecución y luego unirlo con la ruta/proc para obtener la carpeta que, con suerte, necesitará.

Aquí hay un breve ejemplo en Python:

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

Aquí también está el ejemplo 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;
}

Compilarlo con:

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

Salida de Python en una versión reciente de Ubuntu: >>> import os >>> print os.path.join ('/ proc', str (os.getpid ())) / proc / 24346
Luke Stanley

3

No existe un método "garantizado para trabajar en cualquier lugar".

El paso 1 es verificar argv [0], si el programa se inició por su ruta completa, esto (generalmente) tendría la ruta completa. Si se inició por una ruta relativa, se mantiene lo mismo (aunque esto requiere obtener el directorio de trabajo actual, usando getcwd ().

El paso 2, si no se cumple ninguno de los anteriores, es obtener el nombre del programa, luego obtener el nombre del programa de argv [0], luego obtener la RUTA del usuario del entorno y revisar eso para ver si hay un adecuado binario ejecutable con el mismo nombre.

Tenga en cuenta que argv [0] está configurado por el proceso que ejecuta el programa, por lo que no es 100% confiable.


2

gracias: Kiwy
con 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
}

Una vez que alguien hizo un guión de ella
Kiwy

1

También puede obtener la ruta en GNU / Linux con (no probado exhaustivamente):

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 desea que el directorio del ejecutable cambie quizás el directorio de trabajo al directorio del proceso (para medios / datos / etc.), debe soltar todo después del último /:

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

1

El siguiente comando busca el nombre del proceso en la lista de procesos en ejecución y redirige el comando pid a pwdx para encontrar la ubicación del proceso.

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

Reemplace "abc" con su patrón específico.

Alternativamente, si puede configurarlo como una función en .bashrc, puede ser útil si lo necesita con frecuencia.

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

Por ejemplo:

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

18404: /home2/Avro/NIFI

Espero que esto ayude a alguien en algún momento .....


-1

Encuentra la ruta a un nombre de proceso

#!/bin/bash
# @author Lukas Gottschall
PID=`ps aux | grep precessname | grep -v grep | awk '{ print $2 }'`
PATH=`ls -ald --color=never /proc/$PID/exe | awk '{ print $10 }'`
echo $PATH

44
Por favor explique su código. Si lo copia y lo pega desde otro lugar, enlace a la fuente.
Tim

Lo que está haciendo este código, no tan eficiente, es obtener el nombre del proceso (esencialmente, la línea "PID" es un reemplazo para pgrep); en la siguiente línea obtiene la ruta del binario que se está ejecutando ( /proc/$PID/exees un enlace simbólico al archivo ejecutable); y finalmente hace eco de ese enlace simbólico.
Enrico
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.