Unix

在作為分叉程序啟動的 shell 腳本中的奇怪行為

  • July 18, 2014

所以我有一個java程序正在做一些自動化。它必須做的一件事是在隨機機器上找到 JDK 首頁。

因此,我編寫了一個 shell 腳本來嘗試查找 JDK 主目錄,假設它javac位於路徑上。

在本地測試這個 shell 腳本時,我遇到了一些我想理解的相當奇怪的行為。

奇怪的行為歸結為which命令行為相當奇怪。我不知所措的腳本片段以

#/bin/sh
...
if [ -z "$JAVA_HOME" ]; then
   javac -version
   which javac || echo "rv=$?"
   javaExecutable="`which javac`"
   ...

(我添加了javac -versionandwhich javac || echo "rv=$?"只是為了檢查我在分叉程序中是否有一個有效的 PATH )

如果我sh -x用來啟動分叉程序,那麼我會得到以下輸出:

+ '[' -z '' ']'               
+ javac -version              
javac 1.8.0_11                
+ which javac        
+ echo rv=1                   
rv=1                          
++ which javac                
+ javaExecutable=

如果我which用以下功能替換

_which() {
   oldIFS="$IFS"
   IFS=':'
   for p in $PATH
   do
       if [ -x "$p/$1" ]; then
           echo "$p/$1"
           IFS="$oldIFS"
           return 0
       fi
   done
   IFS="$oldIFS"
   return 1
}

然後一切都按我的預期工作。

如果我直接從命令行呼叫我的原始腳本……一切正常

如果我通過…呼叫我的原始腳本,ssh localhost sh -x PathToScript一切正常

所以我找到了解決這個問題的方法……

所以基本上我的 Java 程序如何啟動腳本部分歸咎於……還有其他一些奇怪的地方。

我的 Java 程序正在清理環境以獲得“理智”的東西……

所以Java程式碼看起來像

   ProcessBuilder p = new ProcessBuilder(new String[]{
           "sh",
           "-x",
           "pathToScript.sh"
   }).redirectErrorStream(
           true).redirectOutput(ProcessBuilder.Redirect.INHERIT);
   p.environment().clear();
   p.start();

所以會發生的事情是在本地sh建立它PATH而不是導出它。

當我從

javaExecutable="`which javac`"

要麼

export PATH
javaExecutable="`which javac`"

或者

javaExecutable="`PATH="$PATH" which javac`"

然後一切都開始起作用了

為後代記錄這一點,因為我花了一段時間才將根本原因追溯到我自己的愚蠢(這是程式碼中其他地方的一個很好的理由)

引用自:https://serverfault.com/questions/613626