man 3 system 翻譯

名字

system 執行一個shell命令

概要

#include <stdlib.h>

int system(const char *command);

描述

system()庫函數用fork(2)創建一個子進程,這個子進程通過execl(3)執行command指定的shell命令:

execl("/bin/sh", "sh", "-c", command, (char*) 0);

system()會在命令結束之後返回。

在執行命令的過程中,對於調用system()的進程,SIGCHLD會被阻塞,SIGINT和SIGQUIT會被忽略(對於子進程來說,這些信號還是按照默認的方式來處理)。如果command是NULL,那麼system()會返回一個狀態,表明在本系統上shell是否可用。

返回值

system()的返回值是下面中的一個:

  • 如果command是NULL,如果shell可用就返回一個非零值,如果沒有shell可用就返回0。
  • 如果子進程不能創建,或者它的狀態不能檢索到,那麼返回值是-1。
  • 如果shell不能在子進程裏面執行,那麼返回值就和shell調用_exit(2)終止一樣,返回值是127。
  • 如果所有的系統調用都成功了,那麼返回值就是shell執行命令之後的返回狀態。(一個shell的終止狀態,就是它執行的最後一條命令的終止狀態)。

最後兩種情況下面,返回值是一個“等待狀態”,可以用waitpid(2)中定義的宏去檢測(也就是WIFEXITED(),WEXITSTATUS()等)。

屬性

要查看術語的解釋,請看attribute(7)。

接口 屬性
system() 線程安全性 MT-Safe

規範

POSIX.1-2001, POSIX.1-2008, C89, C99

註釋

system()提供了簡明性和便利性。它處理了所有調用fork(2),execl(3)和waitpid(2),以及關於信號的管理。另外,shell對command做了必須的常用替換和I/O重定向。system()主要的成本是效率比較低。創建進程運行shell和執行shell需要額外的系統調用。

如果_XOPEN_SOURCE特性測試宏定義了的話(在包含任何頭文件之前),那麼當包含<stdlib.h>的時候,waitpid(2)中描述的宏(WEXITSTATUS()等)就都可以用。

就像前文提到的,system()會忽略SIGINT和SIGQUIT。這可能會使得在一個循環裏面調用system()的程序無法中斷,當然除非它們自己檢查子進程的退出狀態,比如:

while (something) {
    inte ret = system("foo");

    if (WIFSIGNALED(ret) &&
        (WTERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT))
            break;
}

根據POSIX.1,沒有確定system()在執行的時候,由pthread_atfork(3)註冊的handlers會不會被調用。對於glibc實現,這些handlers不會被調用。

glibc在2.1.3之前的版本,確認/bin/sh是否可用並不是在command是NULL的時候,而是每次都假設shell可用,然後如果可用就返回1。自從glibc 2.1.3之後,就有了這種確認的方式,因爲即使POSIX.1-2001要求提供一個shell,但是這個shell也可能不可用,或者由於程序調用過chroot(2)(chroot(2)沒有出現在POSIX.1-2001),使得這個shell不可執行。

當然,也有可能一個shell命令的終止狀態值是127,使得它和shell無法在子進程裏面執行這種情況無法區分。

警告

不要在一個由特權的程序(一個設置用戶ID或者設置組ID的程序,或者一個由這樣能力的程序)裏面使用system()。因爲有些環境變量的一些特定的值可能會破壞系統的完整性。比如,PATH可能被篡改,這樣的話任意的程序就可以被來跑在特權模式下面。作爲替代你可以使用exec(3)系列函數,當然除了execlp(3)或者execvp(3),因爲它們同樣適用PATH去搜索可執行程序。

事實上,system()在有set-user-ID或者set-group-ID特權的程序裏面工作的時候不是很合適,這裏的/bin/sh是bash version 2。因爲作爲安全考慮,bash version 2會在啓動的時候丟掉特權。(Debian使用一個不一樣的shell,dash(1),這個倒是不會在啓動的時候丟掉權限)。

作爲system()中command一部分的任何用戶輸入,都要十分仔細的檢查,確保不期望的shell命令和命令選項不被執行。當在一個由特權的程序裏面使用system()的時候這樣的風險就非常大了。

參考

sh(1),execve(2),fork(2),sigaction(2),sigprocmask(2),wait(2),exec(3),signal(7)

版權

本頁是Linux 4.15 man-pages工程的一部分。項目的描述,報bugs相關的信息,以及本頁的最新版本可以在https://www.kernel.org/doc/man-pages/找到。2017-09-15。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章