Trong một môi trường trống rỗng, các thực thi được tìm thấy như thế nào?


7

Đối với mục đích thử nghiệm, tôi đã tạo một tệp nhị phân in $PATHvà gọi whichnhư sau:

#include <stdlib.h>
#include <stdio.h>

int main() {
    char *path = getenv("PATH");

    if (path)
        printf("got a path: %s\n", path);
    else
        printf("got no path\n");

    system("which which");
    return 0;
}

khi tôi chạy nó trong một môi trường trống rỗng thông qua

env -i ./printpath

Tôi nhận được bản in sau:

got no path
/usr/bin/which

Câu hỏi của tôi là: tại sao whichnhị phân chính xác được gọi, ngay cả khi không có $PATH?

Câu trả lời:


11

Bạn đã sử dụng systemchức năng, vì vậy nó sẽ sử dụng shell khác để chạy lệnh which which. Từ man system:

DESCRIPTION
       system()  executes a command specified in command by calling /bin/sh -c
       command, and returns after the command has been completed.  During exe
       cution  of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT
       will be ignored.

Nếu bạn thay đổi which whichlệnh thành echo $PATH:

$ env -i ./a.out 
got no path
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Nếu bạn thay đổi mã để sử dụng execvethay vì system, bạn sẽ nhận được đầu ra dự kiến:

#include <stdlib.h>                                                             
#include <stdio.h>  

int main() {                                                                    
    char *path = getenv("PATH");                                                

    if (path)                                                                   
        printf("got a path: %s\n", path);                                       
    else                                                                        
        printf("got no path\n");                                                

    execve("echo $PATH");                                                       
    return 0;                                                                   
} 

Biên dịch và chạy nó:

$ gcc test.c && env -i ./a.out 
got no path

tôi dự kiến ​​các subshell sẽ kế thừa con đường trống và do đó không có hậu quả. cảm ơn bạn đã chỉ ra quan niệm sai lầm đó!
keppla

1
Subshell không kế thừa đường dẫn trống. Tuy nhiên, là một tính năng của bash (và có lẽ cả các shell khác nữa), nếu nó được bắt đầu với PATH unset, nó đặt nó thành một giá trị mặc định, đó là những gì chúng ta thấy trong echo $PATHví dụ.
Nate Eldredge

3

Trong một môi trường trống, các tệp thực thi không được tìm thấy trừ khi bạn chỉ định đường dẫn đầy đủ. Hãy thử nó với execvp.

Các systemchức năng gọi một vỏ - trên Linux với Glibc, nó gọi /bin/sh(vì vậy không PATHcần thiết). Shell xác định một vài biến của riêng họ ngoài các biến đến từ môi trường. Bạn có thể xem những gì họ xác định bằng cách chạy env -i /path/to/shell -c setvà những gì họ xuất bằng cách chạy env -i /path/to/shell -c export. Cụ thể, cả dash và bash - hai shell mà bạn có thể tìm thấy như /bin/shtrên Linux - đã đặt (nhưng không xuất) PATHthành mặc định của sane, nếu không có trong môi trường. Các shell khác nhau đặt các giá trị khác nhau hoặc không có gì cả.

$ env -i bash -c 'echo $PATH'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ env -i dash -c 'echo $PATH'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ env -i mksh -c 'echo $PATH'
/usr/bin:/bin
$ env -i ksh93 -c 'echo $PATH'

$ env -i zsh -c 'echo $PATH' 
/bin:/usr/bin:/usr/ucb:/usr/local/bin
$ env -i csh -c 'echo $PATH' 
PATH: Undefined variable.
$ env -i tcsh -c 'echo $PATH'
PATH: Undefined variable.

Trên máy của tôi (và của bạn, rõ ràng), whichchính nó là một /bin/shtập lệnh. Shell được gọi bằng cách systemsử dụng biến đường dẫn của chính nó để tìm whichchương trình, nhưng không xuất nó. Shell tự chạy whichscript cũng xác định PATHbiến cho việc sử dụng nội bộ của nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.