मुझे यूनिक्स / लिनक्स में एक प्रक्रिया का मार्ग कैसे मिलता है


138

विंडोज वातावरण में पथ प्राप्त करने के लिए एक एपीआई है जो एक प्रक्रिया चला रहा है। क्या यूनिक्स / लिनक्स में कुछ ऐसा ही है?

या इन वातावरण में ऐसा करने का कोई और तरीका है?

जवाबों:


183

लिनक्स पर, सिम्लिंक /proc/<pid>/exeमें निष्पादन योग्य का पथ होता है। readlink -f /proc/<pid>/exeमान प्राप्त करने के लिए कमांड का उपयोग करें ।

AIX पर, यह फ़ाइल मौजूद नहीं है। आप तुलना कर सकते हैं cksum <actual path to binary>और cksum /proc/<pid>/object/a.out


2
sudoयदि आउटपुट खाली है, तो कुछ सिस्टम अन्य सिस्टम उपयोगकर्ताओं द्वारा बनाए जाते हैं।
Lun4i

63

आप इन तरीकों से आसानी से निर्वासन पा सकते हैं, बस इसे स्वयं आज़माएं।

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

1
यह कमाल का है। मुझे पता था कि मैंने इसे एक स्थान से चलाया था, जिसमें मूल निष्पादन योग्य (कई संस्करणों में से एक) का प्रतीकात्मक लिंक था। pwdx <PID>मुझे प्रतीकात्मक लिंक का स्थान दिया, ताकि मैं लॉग को ढूंढ सकूं और उचित तरीके से प्रक्रिया को रोक सकूं।
नूरशोमिक

1
llआमतौर पर एक उपनाम है alias ll='ls -alF':।
पाब्लो ए

1
अंतिम दो (pwdx और lsof) आपको सही परिणाम नहीं दे सकते हैं। प्रश्न निष्पादन योग्य के लिए पूर्ण पथ के बारे में था। pwdx और lsof आपको प्रक्रिया के मार्ग के बजाय प्रक्रिया का cwd देगा। मुझे लगता है कि jpalecek का उत्तर अधिक सटीक है क्योंकि मूल अनुरोधकर्ता निष्पादन योग्य का वर्णन करने के लिए नरम लिंक के बजाय निष्पादन योग्य के लिए रास्ता पूछता है।
शिमोन

28

थोड़ा देर से, लेकिन सभी जवाब लिनक्स के लिए विशिष्ट थे।

यदि आपको भी यूनिक्स की आवश्यकता है, तो आपको इसकी आवश्यकता है:

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

संपादित: बग मार्क lakata द्वारा रिपोर्ट फिक्स्ड।


हिपरियन को साझा करने के लिए धन्यवाद, लेकिन मुझे एक पीआईडी ​​निर्दिष्ट करने और अपना निर्गमन पथ प्राप्त करने की आवश्यकता थी, क्या यह इस कोड के साथ संभव है?
Noitidart

1
@Noitidart - की जगह "/proc/self/exe"के साथsprintf(foo,"/proc/%d/exe",pid)
मार्क Lakata

2
कृपया ध्यान दें कि रीडलिंक परिणाम को समाप्त नहीं करता है, इसलिए इस कोड में अपरिभाषित व्यवहार है।
मार्क लकाटा

थैंक यू @ मर्कलकाता! :)
Noitidart

@MarkLakata
Hiperion


11

pwdx <process id>

यह कमांड प्रक्रिया पथ को लाएगा जहां से वह क्रियान्वित हो रहा है।


जानकारी प्राप्त करने के लिए सवाल एपीआई के बारे में है, लेकिन वैसे भी धन्यवाद।
lsalamon

4

लिनक्स में हर प्रक्रिया का अपना एक फोल्डर होता है /proc। इसलिए आप getpid()रनिंग प्रक्रिया की सहायता प्राप्त करने के लिए उपयोग कर सकते हैं और फिर उस पथ /procसे जुड़ सकते हैं जिस फ़ोल्डर की आपको उम्मीद है।

यहाँ पायथन में एक छोटा उदाहरण दिया गया है:

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

यहां एएनएसआई सी में उदाहरण दिया गया है:

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

इसके साथ संकलित करें:

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

उबंटू के हालिया संस्करण पर पायथन आउटपुट: >>> आयात ओएस >>> प्रिंट os.path.join ('/ proc', str (os.getpid ())) / proc / 24346
ल्यूक स्टेनली

3

कोई "कहीं भी काम करने की गारंटी नहीं है" विधि।

चरण 1 को argv [0] को जांचना है, अगर कार्यक्रम को उसके पूर्ण पथ द्वारा शुरू किया गया था, तो यह (आमतौर पर) पूरा पथ होगा। यदि यह एक रिश्तेदार पथ द्वारा शुरू किया गया था, तो वही होल्ड (हालांकि इसके लिए getcwd का उपयोग करके, वर्तमान कार्यशील निर्देशिका प्राप्त करने की आवश्यकता होती है)।

चरण 2, यदि उपरोक्त में से कोई भी नहीं है, प्रोग्राम का नाम प्राप्त करना है, तो argv [0] से प्रोग्राम का नाम प्राप्त करें, फिर उपयोगकर्ता के पर्यावरण से पाएं और देखें कि क्या कोई उपयुक्त है एक ही नाम के साथ निष्पादन योग्य बाइनरी।

ध्यान दें कि argv [0] प्रोग्राम को निष्पादित करने वाली प्रक्रिया द्वारा निर्धारित किया गया है, इसलिए यह 100% विश्वसनीय नहीं है।


2

धन्यवाद: Kiwy
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
}

NIce कि किसी ने इसकी एक स्क्रिप्ट बनाई
किवी

1

आप जीएनयू / लिनक्स पर भी पथ प्राप्त कर सकते हैं (पूरी तरह से परीक्षण नहीं किया गया है):

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

यदि आप कार्यशील निर्देशिका को प्रक्रिया की निर्देशिका (मीडिया / डेटा / आदि के लिए) में बदलने के लिए निष्पादन योग्य की निर्देशिका चाहते हैं, तो आपको अंतिम / के बाद सब कुछ छोड़ने की आवश्यकता है:

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

1

नीचे दी गई कमांड चल रही प्रक्रिया सूची में नाम के लिए खोज करती है, और प्रक्रिया के स्थान का पता लगाने के लिए pwdx कमांड पर रीडायरेक्ट करती है।

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

अपने विशिष्ट पैटर्न के साथ "एबीसी" को बदलें।

वैकल्पिक रूप से, यदि आप इसे .bashrc में एक फ़ंक्शन के रूप में कॉन्फ़िगर कर सकते हैं, तो आपको अक्सर उपयोग किए जाने के लिए इसे उपयोग करने की आवश्यकता हो सकती है।

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

उदाहरण के लिए:

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

18404: /home2/Avro/NIFI

उम्मीद है कि यह किसी को मदद करता है .....


-1

प्रक्रिया नाम के लिए पथ खोजें

#!/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
कृपया अपना कोड स्पष्ट करें। यदि आप इसे कहीं और से कॉपी और पेस्ट करते हैं, तो कृपया स्रोत से लिंक करें।
टिम

यह इतना कुशल नहीं है-कोड क्या कर रहा है प्रक्रिया नाम मिल रहा है (अनिवार्य रूप से, "पीआईडी" लाइन एक प्रतिस्थापन है pgrep); अगली पंक्ति में इसे बाइनरी के निष्पादित होने का मार्ग मिलता है ( /proc/$PID/exeयह निष्पादन योग्य फ़ाइल के लिए एक सिमलिंक है); और अंत में यह उस सहानुभूति को ग्रहण करता है।
एनरिको
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.