Unix / Linux'ta bir işlemin yolunu nasıl alırım


138

Windows ortamında, bir işlemi çalıştıran yolu elde etmek için bir API vardır. Unix / Linux'ta benzer bir şey var mı?

Yoksa bu ortamlarda bunu yapmanın başka bir yolu var mı?

Yanıtlar:


183

Linux'ta, sistem bağlantısı /proc/<pid>/exeyürütülebilir dosyanın yoluna sahiptir. readlink -f /proc/<pid>/exeDeğeri almak için komutu kullanın .

AIX üzerinde bu dosya yok. Karşılaştırabilir cksum <actual path to binary>ve cksum /proc/<pid>/object/a.out.


2
sudoçıktı boşsa, bazı işlemler diğer sistem kullanıcıları tarafından oluşturulur.
Lun4i

63

Exe'yi bu yollarla kolayca bulabilirsiniz, sadece kendiniz deneyin.

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

1
Bu harika. Orijinal yürütülebilir dosyaya (birçok versiyondan biri) sembolik bağlantısı olan bir yerden çalıştırdığımı biliyordum. pwdx <PID>günlükleri bulabilmem ve süreci düzgün bir şekilde durdurabilmem için bana sembolik bağlantının yerini verdi.
NurShomik

1
llgenellikle bir takma addır alias ll='ls -alF'.
Pablo A

1
Son iki (pwdx ve lsof) size doğru sonucu vermeyebilir. Soru, çalıştırılabilir dosyanın tam yolu hakkındaydı. pwdx ve lsof, işlemin yolu yerine size işlemin cwd'sini verecektir. Orijinal istekte çalıştırılabilir açıklayan yumuşak bağlantı yerine yürütülebilir yol yol istedi gibi jpalecek cevabı daha doğru olduğunu düşünüyorum.
Şimon

28

Biraz geç, ama tüm cevaplar linux'a özgüdür.

Ayrıca unix'e ihtiyacınız varsa, buna ihtiyacınız vardır:

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

REDAKTE: Mark LAKATA tarafından rapor hata düzeltildi.


Hiperion'u paylaştığınız için teşekkürler, ancak bir PID belirtmem ve exe yolunu almam gerekiyordu, bu kodla mümkün mü?
Noitidart

1
@Noitidart - değiştirmek "/proc/self/exe"ilesprintf(foo,"/proc/%d/exe",pid)
Mark LAKATA

2
Lütfen readlink'in sonucu sonlandırmayacağını unutmayın, bu nedenle bu kod tanımsız davranışa sahiptir.
Mark Lakata

Teşekkürler @MarkLakata! :)
Noitidart

@MarkLakata
Hiperion

14

Kullanırım:

ps -ef | grep 786

786 yerine PID veya işlem adınızı yazın.


11

pwdx <process id>

Bu komut, işlem yolunu yürütüldüğü yerden getirecektir.


Soru, bilgi almak için API ile ilgili, ancak yine de teşekkürler.
lsalamon

4

Linux'ta her işlemin kendi klasörü vardır /proc. Böylece getpid()çalışan işlemin pid'ini almak ve daha sonra /procumarım ihtiyacınız olan klasörü almak için yolla birlikte kullanabilirsiniz.

Python'da kısa bir örnek:

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

İşte ANSI C'deki örnek:

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

Şununla derleyin:

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

Ubuntu son sürümüne Python çıkışı: >>> import os >>> print os.path.join ( '/ proc', str (os.getpid ())) / proc / 24346
Luke Stanley

3

"Her yerde çalışmayı garanti eden" bir yöntem yoktur.

Adım 1 argv [0] 'ı kontrol etmektir, eğer program tam yolu ile başlatılmışsa, bu (genellikle) tam yola sahip olacaktır. Göreli bir yolla başlatılmışsa, aynı tutar (getcwd () kullanarak geçerli çalışma dizinini almayı gerektirir).

Adım 2, yukarıdakilerin hiçbiri programın adını almıyorsa, programın adını argv [0] 'dan almak, daha sonra kullanıcının PATH'ını ortamdan almak ve uygun olup olmadığını görmek için bunu yapın. aynı ada sahip yürütülebilir ikili dosya.

Argv [0] 'un programı yürüten işlem tarafından ayarlandığını unutmayın, bu yüzden% 100 güvenilir değildir.


2

teşekkürler: AIX ile Kiwy
:

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
}

Güzel biri bir senaryo yaptı
Kiwy

1

Ayrıca GNU / Linux üzerinde de yol alabilirsiniz (kapsamlı olarak test edilmemiştir):

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

Çalışma dizinini belki de çalışma dizinini işlemin dizinine değiştirmek için (medya / veri / vb.) İstiyorsanız, her şeyi sondan sonra bırakmanız gerekir:

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

1

Aşağıdaki komut, çalışan işlem listesinde işlemin adını arar ve işlemin konumunu bulmak için pid'i pwdx komutuna yeniden yönlendirir.

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

"Abc" yi kendi modelinizle değiştirin.

Alternatif olarak, .bashrc dosyasında bir işlev olarak yapılandırabiliyorsanız, bunun sıkça kullanılmasını istiyorsanız, kullanışlı bulabilirsiniz.

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

Örneğin:

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

18404: /home2/Avro/NIFI

Umarım bu bazen birine yardımcı olur .....


-1

İşlem adının yolunu bulma

#!/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
Lütfen kodunuzu açıklayınız. Başka bir yerden kopyalayıp yapıştırdıysanız, lütfen kaynağa bağlantı verin.
Tim

Bu kadar verimli olmayan kodun yaptığı şey işlem adını almaktır (esasen "PID" satırı yerine geçer pgrep); sonraki satırda çalıştırılan ikili dosyanın yolunu alır ( /proc/$PID/exeyürütülebilir dosyaya bir sembolik bağlantıdır); ve son olarak da bu sembolik bağı yansıtıyor.
Enrico
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.