2013-03-20 72 views
0

我有很多問題阻止了我整天。Bash:不能調用函數;沒有這樣的文件或目錄

我有許多功能文件與各種功能的基礎上使用,即。 SSH,測井等

我有一個腳本運行在那裏我添加錯誤的錯誤數組是全球性的。我有一個錯誤陷阱,在另一個'exit_functions'文件中調用腳本。

在這種exit_functions文件我做各種事情,但我有問題的部分是這個數組的運行,並翻出這實際上是命令數組元素的循環。這些命令是函數內的一個函數文件已被包含在調用腳本中使用正常。/path/to/functions_file語法。

我所有的其他功能,如記錄等正在努力走出exit_functions文件,它只是不能叫這些特定功能。我得到一個錯誤:

/functions/exit_functions: line 109: closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck: No such file or directory 

現在,killSSHTunnel的是,在先前已就像其他功能的文件已被列入包括一個功能文件坐在一個功能。我只使用這些函數調用從數組中獲取此錯誤。

我不知道我是否已經正確地描述它 - 請讓我知道如果我可以提供任何其他信息。下面


編輯全功能代碼:

/功能/ exit_functions文件: exitTrap(){ 當地LCL_SCRIPT_ERROR

if [ $ERR_COUNT_EXIT_FUNCT -gt 0 ]; then 
     for LCL_SCRIPT_ERROR in "${ERROR_ARRAY[@]}"; do 
      case $LCL_SCRIPT_ERROR in 
       SVN_IMPORT  ) # match the SVN_IMPORT error name and search for specific commands to run 
            exitMsg "$LCL_SCRIPT_ERROR; 111" 
            executeErrorActions $LCL_SCRIPT_ERROR 

            exitScript 111 
            ;; 

       *    ) exitMsg "$LCL_SCRIPT_ERROR; 255" 
            exitScript 255 
            ;; 
      esac 
     done 
    fi 
} 

所以我的測試代碼引入了一個錯誤狀態最終調用上面的函數(exitTrap)。它已經填充了一個名爲ERROR_ARRAY的數組。

所以executeErrorActions功能,也在/功能/ exit_functions,循環關聯數組,ERROR_ACTION_ARRAY,尋找一個叫鍵(在此測試)SVN_IMPORT了。當它找到這個鍵時,它正在尋找一個以':'分隔的字符串。每個分隔的部分將是一個單獨的命令,當出現這種錯誤情況時我將運行它。在我的測試我有一個條目(沒有分隔符),其僅僅是:* closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck*

現在,有了以下的功能,它工作正常,當我包括之間的部分IFS =和未設置的IFS,而是使用下面具有雙註釋哈希的單行。當我介紹IFS分隔打破串起我得到的錯誤:

/functions/exit_functions: line 109: closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck: No such file or directory

executeErrorActions(){ 
    if [ ! $# -eq 1 ]; then 
     return 1 
    fi 

    local ERROR_NAME=$1 
    local ERROR_ACTION 

    #ERROR_KEY="SVN_IMPORT" 

    for ERROR_ACTION in ${!ERROR_ACTION_ARRAY[@]}; do 
     #echo KEY: $i VALUE: ${ERROR_ACTION_ARRAY[$i]} 
     if [ $ERROR_NAME == $ERROR_ACTION ]; then 

      ##$(${ERROR_ACTION_ARRAY[$ERROR_ACTION]}) 

      IFS=":" 
      for i in ${ERROR_ACTION_ARRAY[$ERROR_ACTION]}; do 
       $i 
      done 
      unset IFS 
      return 0 
     fi 
    done 
} 

下面是使用兩個測試運行的設定-x輸出「:」 delimitered命令,同樣關閉上面的功能功能和簡單的ls -la調用。

addError SVN_IMPORT closeSSHTunnel $SSH_TUNNEL_LCK_FILE:ls -la 

這是設置-x輸出:

+ executeErrorActions SVN_IMPORT 
+ '[' '!' 1 -eq 1 ']' 
+ local ERROR_NAME=SVN_IMPORT 
+ local ERROR_ACTION 
+ for ERROR_ACTION in '${!ERROR_ACTION_ARRAY[@]}' 
+ '[' SVN_IMPORT == SVN_IMPORT ']' 
+ IFS=: 
+ for i in '${ERROR_ACTION_ARRAY[$ERROR_ACTION]}' 
+ 'closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck' 
/functions/exit_functions: line 116: closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck: No such file or directory 
+ for i in '${ERROR_ACTION_ARRAY[$ERROR_ACTION]}' 
+ 'ls -la' 
/functions/exit_functions: line 116: ls -la: command not found 
+ unset IFS 
+ return 0 

注意如何他們中的一個說:「沒有這樣的文件或目錄,我用下面的addError函數調用這些添加到ERROR_ACTION_ARRAY另一個說'找不到命令'。這是現在第2天試圖解決這個問題!

我的結論是,IFS更改和字符串分裂導致問題。

EDIT 2

如果我移動IFS張望了一下電話,並終止對IFS的「:」內循環炭,然後執行調用它所有的作品後,再次確立它! !!!!

for ERROR_ACTION in ${!ERROR_ACTION_ARRAY[@]}; do 
     #echo KEY: $i VALUE: ${ERROR_ACTION_ARRAY[$i]} 
     if [ $ERROR_NAME == $ERROR_ACTION ]; then 
      #$(${ERROR_ACTION_ARRAY[$ERROR_ACTION]}) 
      IFS=$':' 
      for i in ${ERROR_ACTION_ARRAY[$ERROR_ACTION]}; do 
       unset IFS 
       $i 
       IFS=$':' 
      done 
      unset IFS 
      return 0 
     fi 
done 

任何人都可以解釋這一點嗎?

+1

文件'/ tmp/ssh_tunnel_iA0yj.lck'是否存在? – choroba 2013-03-20 12:57:20

+0

你可以發佈'killSSHTunnel'的代碼並指出哪一行是第109行嗎? – chepner 2013-03-20 13:01:46

+0

@choroba - 我發佈了下面的代碼作爲答案,以便我可以獲得代碼突出顯示。我討厭我不能在這些評論中粘貼代碼。 – ilium007 2013-03-20 13:14:50

回答

1

這是因爲你的IFS設置爲「:」 - bash使用IFS將變量拆分爲單詞(即函數名稱與其參數),而不是單獨的命令。因此,它試圖運行名爲closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck的命令,而不是命令closeSSHTunnel,命令/tmp/ssh_tunnel_iA0yj.lck

$ ERROR_ACTION="echo something" 
$ $ERROR_ACTION 
something 
$ IFS=":" 
$ $ERROR_ACTION 
-bash: echo something: command not found 
$ ERROR_ACTION="echo:something" 
$ $ERROR_ACTION 
something 

如果您希望能夠包含多個命令,則必須自行拆分它們。

編輯:考慮到更完整的腳本摘錄,你需要的是對IFS設置爲:當你執行命令時,for拆分命令,但要恢復正常:

... 
saveIFS="$IFS" 
IFS=":" 
for i in ${ERROR_ACTION_ARRAY[$ERROR_ACTION]}; do 
    IFS="$saveIFS" 
    $i 
done 
IFS="$saveIFS" 
「」

這會重置IFS,而不是嚴格需要,但是比添加邏輯來確定實際需要重置的時間(以及在未執行循環的情況下最終重置時)會更容易。

+0

是的 - 我正在那樣分裂。所以我的命令是這樣的:「closeSSHTunnel user PID.lck」,當我只有一個命令並且沒有IFS調用來拆分字符串時,它一切正常。只要我包含IFS =「:」並拆分字符串(即使我只有一個元素沒有分隔符),我得到文件未找到錯誤。我想知道如果字符串split是圍繞結果或單詞引用單引號。 – ilium007 2013-03-21 00:22:25

+0

我已經發布了代碼和原始問題中的問題的更好的說明。 – ilium007 2013-03-21 00:34:42

0

我不知道這是否是正確的方法來做到這一點,但我用IFS =「:」打開字符串並將其放入數組,然後重置IFS。然後我循環這些命令來執行它們。所有的工作。

executeErrorActions(){ 
    if [ ! $# -eq 1 ]; then 
     return 1 
    fi 

    local ERROR_NAME=$1 
    local ERROR_ACTION 
    local ACTION_ARRAY 
    local ACTION 

    if [ ${#ERROR_ACTION_ARRAY[@]} -gt 0 ]; then 
     for ERROR_ACTION in ${!ERROR_ACTION_ARRAY[@]}; do 
      if [ $ERROR_NAME == $ERROR_ACTION ]; then 
       if [ ${#ERROR_ACTION_ARRAY[$ERROR_ACTION]} -gt 0 ]; then 
        IFS=$':' 
        ACTION_ARRAY=(${ERROR_ACTION_ARRAY[$ERROR_ACTION]}) 
        unset IFS 
        for ACTION in ${!ACTION_ARRAY[@]}; do 
         exitMsg "Running action for $ERROR_ACTION" 
         ${ACTION_ARRAY[$ACTION]} 
         if [ $? -eq 0 ]; then 
          exitMsg "Error action succeeded" 
         else 
          exitMsg "Error action failed" 
          return 1 
         fi 
        done 
        return 0 
       else 
        return 1 #no contents in the array element; no actions to run; maybe there should have been; return error 
       fi 
      else 
       return 0 #no matching actions for this error; still return success 
      fi 
     done 
    else 
     return 0 #action array is empty 
    fi 
} 
相關問題