câu trả lời này có thể đến hơi muộn, nhưng tôi đã gặp vấn đề tương tự và câu trả lời được chấp nhận dường như không làm tôi hài lòng lắm, vì vậy tôi đã điều tra thêm một chút.
Điều làm tôi bận tâm là thực tế có $0
hoặc $PROGRAM_NAME
không thực sự nắm giữ thông tin chính xác về những gì người dùng đã nhập . Nếu tập lệnh Ruby của tôi nằm trong thư mục PATH và người dùng đã nhập tên thực thi (không có bất kỳ định nghĩa đường dẫn nào như ./script
hoặc /bin/script
), nó sẽ luôn mở rộng thành đường dẫn tổng.
Tôi nghĩ rằng đây là một trang web thiếu hụt của Ruby, vì vậy tôi đã thử tương tự với Python và với sự thất vọng của tôi ở đó, nó không khác gì.
Một người bạn đề nghị tôi một hack để tìm kiếm real thing
trong /proc/self/cmdline
, và kết quả là: [ruby, /home/danyel/bin/myscript, arg1, arg2...]
(ngăn cách bởi null-char). Nhân vật phản diện ở đây là execve(1)
mở rộng đường dẫn đến đường dẫn tổng thể khi nó chuyển nó cho một thông dịch viên.
Chương trình C ví dụ:
extern char** environ;
int main() {
char ** arr = malloc(10 * sizeof(char*));
arr[0] = "myscript";
arr[1] = "-h";
arr[2] = NULL;
execve("/home/danyel/bin/myscript", arr, environ);
}
Đầu ra: ʻCách sử dụng: / home / danyel / bin / myscript FILE ...
Để chứng minh rằng đây thực sự là một sự execve
vật và không phải từ bash, chúng ta có thể tạo một trình thông dịch giả không làm gì khác ngoài việc in ra các đối số được truyền cho nó:
// interpreter.c
int main(int argc, const char ** argv) {
while(*argv)
printf("%s\n", *(argv++));
}
Chúng tôi biên dịch nó và đặt nó trong một thư mục đường dẫn (hoặc đặt đường dẫn đầy đủ sau shebang) và tạo một tập lệnh giả trong ~/bin/myscript/
Hi there!
Bây giờ, trong main.c của chúng tôi:
extern char** environ;
int main() {
char ** arr = malloc(10 * sizeof(char*));
arr[0] = "This will be totally ignored by execve.";
arr[1] = "-v";
arr[2] = "/var/log/apache2.log";
arr[3] = NULL;
execve("/home/danyel/bin/myscript", arr, environ);
}
Biên dịch và chạy ./main
: thông dịch viên / home / danyel / bin / myscript -v /var/log/apache2.log
Lý do đằng sau điều này rất có thể là nếu tập lệnh nằm trong PATH của bạn và đường dẫn đầy đủ không được cung cấp, trình thông dịch sẽ nhận ra đây là No such file
lỗi, điều này xảy ra nếu bạn làm vậy: ruby myrubyscript --options arg1
và bạn không ở trong thư mục có tập lệnh đó .