簡單來講,就是我編寫了一段代碼 exec('dir'),php會報錯,提示 Unable to fork [dir] ,而且exec函數第三個參數返回值爲-1。爲了解決這個問題,我作了大量搜索,花了幾乎一整的時間,嘗試了網上提到的各類辦法,最終問題得以解決,不過仍是有不少不太清楚的地方,本文只是記錄一下心得。php
個人環境
Windows Server 2012 R2, IIS-8.5, PHP-5.6.28windows
問題查找順序
1. 肯定:檢查php.ini的disable_functions是否包含了exec
2. 肯定:C:\Windows\System32\ 路徑被加入到環境變量中
2. IIS默認會創建一個IIS_IUSRS組,還有一個默認用戶叫IUSR
3. php官網提到,exec函數會先打開cmd.exe,所以網上有帖子說須要讓用戶"IUSR"有執行cmd.exe的權限,我不肯定是否是必定要這樣作
4. C:\Windows\System32 以及 C:\Windows\SysWOW64 都有cmd.exe,還不太明白這2個的區別。
5. 貌似環境變量裏有一個變量叫 ComSpec,指向了 C:\Windows\System32
6. 微軟官方提供了一個工具Procmon.exe,大概能夠監視一些東西。
https://docs.microsoft.com/en-us/sysinternals/
https://live.sysinternals.com/
最終監視出來的結果,貌似是php-cgi.exe建立了一個進程cmd.exe,而後執行dir命令,不過cmd.exe的完整路徑爲何是 C:\Windows\SysWOW64\cmd.exe
7. IIS好像有多處地方能夠修改user
1. 應用程序池(Application Pools)-> 高級設置(Advacned Settings) -> 標識(Identity)
2. 網站(Sites) -> 身份認證(Authentication) -> 匿名身份認證(Anonymous Authentication) -> 編輯(Edit)
3. 網站(Sites) -> 高級設置(Advacned Settings) -> 物理路徑憑據(Physical Path Credentials)
8. 使用 get_current_user 函數能夠獲取到當前php究竟是以哪一個用戶在運行
9. Windows任意文件或者目錄下,查看指定用戶的權限
右鍵 -> 屬性 -> 安全 -> 高級 -> 有效訪問 -> 選擇用戶 -> "輸入用戶名,點檢查名稱,肯定" -> 查看有效訪問
以上是不少人提到的有多是權限不足形成的問題,各類測試下來,我發現並非權限形成的,繼續又查了好多資料!
10. 打開IIS首頁 -> FastCGI Settings -> Edit -> Advacned Settings.Protocol由NamedPipe改成TCP,問題解決!
11. 繼續查資料,爲何NamedPipe不行,其實我也不懂這玩意。大概就是fascgi和其餘應用程序通訊的方式,由於我在第7點處都指定了網絡用戶,致使了在建立pipe時(可能就是第6點提到的),權限不足引發的。
12. 最終解決方案:FastCGI Protocol繼續保持NamedPipe(由於網上說windows下這種協議更快),第7點提到的3處分別爲
1. 指定網絡用戶,不過在IIS_IUSRS組裏
2. 使用應用程序池標識(Application pool identity)
3. 留空白,應用程序用戶(經過身份認證)(Application user(pass-through authentication))
13. 關於NamedPipe的資料
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365600(v=vs.85).aspx
https://stackoverflow.com/questions/4098549/minimum-os-permissions-required-to-create-named-pipe-wcf
https://serverfault.com/questions/247064/permission-needed-for-named-pipes-on-windows-2008
https://stackoverflow.com/questions/21115821/what-is-fcgi-x-pipe-in-the-php-superglobal-array-and-what-is-it-used-for安全