2013-03-20 71 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 
} 
相关问题