項目中為了方便快捷的處理問題,PHP 結合 shell 腳本非常常見。
一、怎么用
exec (string command [, string array [, int return_var]]) // string command 命令行 // string array 命令行返回的所有結果,是個數組 // int return_var 命令運行結果,正常為 0,否則有錯誤。
二、常見問題
exec() 函數用法很簡單,但是使用過程中很可能會出現一些問題。
1、執行命令后毫無反應,不知道發生了什么
首先檢查 PHP 配置,確認是否開啟了安全模式。
safe_mode=on|off
① 默認情況下,安全模式是關閉的,啟用時,一些限制會生效。
② 所有輸入輸出函數,只能用於與調用這些函數的腳本有相同擁有者的文件。
fopen() file() require()
③ 只有當腳本位於safe_mode_exec_dir配置指定的目錄,才能通過函數 popen()、system()、exec() 等執行腳本。
④ 安全模式受影響的函數
apache_request_headers() backticks() chdir() chgrp() chmode() chown() copy() dbase_open() dbmopen() dl() exec() filepro() filepro_retrieve() filepro_rowcount() fopen() header() highlight_file() ifx_* ingres_* link() mail() max_execution_time() mkdir() move_uploaded_file() mysql_*
parse_ini_file() passthru() pg_lo_import() popen() posix_mkfifo() putenv() rename() zmdir() set_time_limit() shell_exec() show_source() symlink() system() touch()
2、簡單 linux 命令可以執行,涉及到處理文件的命令不好用。
exec('cmd.sh > /tmp/cmd.log 2>&1', $out, $status)
把執行腳本 cmd.sh 的正常異常輸出寫入 /tmp/cmd.log 文件。然后根據錯誤提示對症下葯。
注意為了避免文件權限問題,log 文件一定要放在所有用戶都可寫入的目錄。
3、log 文件中提示文件權限問題
① 在 PHP 文件中打印執行文件的用戶,就會明白為什么會出現權限問題。
echo shell_exec('whoami');
② 假設執行文件的用戶是 daemon,但是要處理的文件是另外的用戶,就需要指定用戶執行 sh 腳本。
// runuser 指定執行腳本的用戶
// runuser 只能用於 root 用戶,所以前面加 sudo
exec("sudo runuser owner -s /bin/bash -c 'cmd.sh $id' >> /tmp/cmd.log 2>&1");
4、提示 sudo: no tty present and no askpass program specified
是因為用 sudo 相當於用 root 用戶權限, 需要設置 daemon 用戶免密碼登錄到 root
# vim /etc/sudoers daemon ALL = NOPASSWD: ALL
這樣 exec() 就可以順利執行啦。
Linux 中要注意文件權限問題。
