Bagaimana cara mendapatkan jalur proses di Unix / Linux


143

Di lingkungan Windows ada API untuk mendapatkan jalur yang menjalankan proses. Apakah ada yang serupa di Unix / Linux?

Atau adakah cara lain untuk melakukannya di lingkungan ini?

Jawaban:


189

Di Linux, symlink /proc/<pid>/exememiliki jalur yang dapat dieksekusi. Gunakan perintah readlink -f /proc/<pid>/exeuntuk mendapatkan nilainya.

Di AIX, file ini tidak ada. Anda bisa membandingkan cksum <actual path to binary>dan cksum /proc/<pid>/object/a.out.


2
sudojika output kosong, beberapa proses dibuat oleh pengguna sistem lain.
Lun4i

66

Anda dapat menemukan exe dengan mudah dengan cara-cara ini, coba saja sendiri.

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

1
Ini luar biasa. Saya tahu saya menjalankannya dari lokasi yang memiliki tautan simbolis ke eksekusi asli (salah satu dari banyak versi). pwdx <PID>memberi saya lokasi tautan simbolis sehingga saya dapat menemukan log dan menghentikan proses dengan cara yang benar.
NurShomik

1
llbiasanya adalah alias: alias ll='ls -alF'.
Pablo Bianchi

1
Dua yang terakhir (pwdx dan lsof) mungkin tidak memberikan hasil yang benar. Pertanyaannya adalah tentang jalur lengkap ke eksekusi. pwdx dan lsof akan memberi Anda cwd proses, bukan jalur ke proses. Saya pikir jawaban jpalecek lebih akurat karena pemohon asli meminta jalur ke file yang dapat dieksekusi daripada tautan lunak yang menjelaskan file yang dapat dieksekusi.
Shimon

28

Sedikit terlambat, tetapi semua jawaban khusus untuk linux.

Jika Anda juga membutuhkan unix, maka Anda membutuhkan ini:

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

DIEDIT: Memperbaiki bug yang dilaporkan oleh Mark lakata.


Terima kasih telah berbagi Hiperion, tetapi saya perlu menentukan PID dan mendapatkan jalur exe-nya, apakah itu mungkin dengan kode ini?
Noitidart

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

2
Harap dicatat bahwa tautan baca tidak membatalkan hasil, jadi kode ini memiliki perilaku yang tidak ditentukan.
Mark Lakata

14

Saya menggunakan:

ps -ef | grep 786

Ganti 786 dengan PID atau nama proses Anda.


tetapi tidak menunjukkan proses dir
Stalinko

12

pwdx <process id>

Perintah ini akan mengambil jalur proses dari tempat ia dijalankan.


Pertanyaannya adalah tentang API untuk mendapatkan informasi, tapi terima kasih.
lsalamon

4

Di Linux setiap proses memiliki foldernya sendiri /proc. Jadi Anda bisa menggunakan getpid()pid dari proses yang sedang berjalan dan kemudian menggabungkannya dengan path /procuntuk mendapatkan folder yang diharapkan Anda butuhkan.

Berikut contoh singkat dengan Python:

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

Inilah contoh di ANSI C juga:

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

Kompilasi dengan:

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

Keluaran Python pada versi terbaru Ubuntu: >>> import os >>> print os.path.join ('/ proc', str (os.getpid ())) / proc / 24346
Luke Stanley

3

Tidak ada metode "dijamin untuk bekerja di mana saja".

Langkah 1 adalah memeriksa argv [0], jika program dimulai dengan jalur lengkapnya, ini (biasanya) akan memiliki jalur lengkap. Jika itu dimulai oleh jalur relatif, penahanan yang sama (meskipun ini membutuhkan direktori kerja saat ini, menggunakan getcwd ().

Langkah 2, jika tidak ada satu pun dari yang di atas berlaku, adalah mendapatkan nama program, kemudian mendapatkan nama program dari argv [0], kemudian dapatkan PATH pengguna dari lingkungan dan lakukan itu untuk melihat apakah ada yang cocok biner yang dapat dieksekusi dengan nama yang sama.

Perhatikan bahwa argv [0] disetel oleh proses yang menjalankan program, jadi tidak 100% dapat diandalkan.


2

terima kasih: Kiwy
dengan 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
}

1

Anda juga bisa mendapatkan jalur di GNU / Linux dengan (tidak diuji secara menyeluruh):

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

Jika Anda ingin direktori yang dapat dieksekusi untuk mungkin mengubah direktori kerja ke direktori proses (untuk media / data / etc), Anda perlu menghapus semuanya setelah / terakhir:

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

1

Perintah di bawah ini mencari nama proses dalam daftar proses yang sedang berjalan, dan mengarahkan perintah pid ke pwdx untuk menemukan lokasi proses.

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

Gantikan "abc" dengan pola spesifik Anda.

Alternatifnya, jika Anda dapat mengkonfigurasinya sebagai fungsi dalam .bashrc, Anda mungkin merasa berguna untuk menggunakannya jika Anda membutuhkan ini untuk sering digunakan.

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

Misalnya:

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

18404: /home2/Avro/NIFI

Semoga ini membantu seseorang kapan-kapan .....


-1

Temukan jalur ke nama proses

#!/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

4
Tolong jelaskan kode Anda. Jika Anda menyalin dan menempelkannya dari tempat lain, harap tautkan ke sumbernya.
Tim

Apa yang dilakukan kode -tidak begitu efisien- adalah mendapatkan nama proses (pada dasarnya, baris "PID" adalah penggantinya pgrep); di baris berikutnya ia mendapatkan jalur biner yang sedang dieksekusi ( /proc/$PID/exeadalah symlink ke file yang dapat dieksekusi); dan akhirnya symlink itu menggemakan.
Enrico
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.