为什么我的脚本退出循环

为什么我的脚本退出循环

我不明白为什么我的脚本在第一行之后离开循环。看来它中断了,因为我在 deleteUser 函数中调用另一个脚本。

这是我的脚本的摘录:

[...]

function deleteUser
{
  nfsserver="/local/scripts/find_home_in_nfs.sh ${1}"
  ssh -n $nfsserver "rm -rf /home/${1}"
  ssh ldap "sudo deleteUser ${1}"
  userHome ${1}
}

cat myFile | while read line
do
  username=`echo ${line} | awk -F" " '{print $1}'`
  action=`echo ${line} | awk -F" " '{print $2}'`

  if [ "${action}" == "d" ]; then
     deleteUser ${username}
  elif [ "${action}" == "a" ]; then
     addUser ${username}
  fi
done

我尝试重写脚本的简化版本,而不调用“find_home_in_nfs.sh”(它与所有 NFS 服务器进行大量 ssh 连接以查找主位置),并且它有效。

但我必须使用它,我无法修改它。有没有办法让这个 while 循环起作用?

答案1

您可以大大简化循环,如以下示例所示:

while read username action
do
   if [ "${action}" == "d" ]; then
      echo "deleteUser ${username}"
   elif [ "${action}" == "a" ]; then
      echo "addUser ${username}"
   fi
done < myFile

答案2

基本问题是ssh读取大部分文件。read line从文件中读取第一行,然后它运行(除其他外),其中ssh -n $nfsserver "rm -rf /home/${1}"(因为-n)不从标准输入读取,然后它运行ssh ldap "sudo deleteUser ${1}"没有从标准输入读取的内容-n,因此读取它可以读取的所有内容(即整个文件的其余部分)并将其发送到远程计算机,远程计算机将忽略它。然后,下一次迭代开始,read line尝试从文件中读取,但它位于末尾,因此退出循环。

您可以通过添加-n其他命令(以及可能运行的ssh任何其他命令)来解决此问题,ssh添加类似于</dev/null可能从标准输入读取的所有其他命令的内容...但我更喜欢发送文件以通过标准输入以外的其他内容进行读取,这样可以跳过整个混乱。以下是如何使用 FD #3 发送和读取它:

while read line <&3; do
    ...
done 3<myFile

read将此与@fpmurphy1的让处理字段分割的建议和@Kusalananda的使用相结合case给出:

while read username action <&3
do
   case "$action" in
       d) deleteUser "$username" ;;
       a) addUser "$username" ;;
       *) echo "Unknown action: $action on user $username" >&2 ;;
   esac
done 3< myFile

顺便说一句,如果您要一次添加和删除大量用户,我会尝试进一步优化它。在当前版本中,它为每个用户与每个服务器打开一个单独的 ssh 会话。打开到每台服务器的单个连接并通过该连接处理所有用户会更快。缺点:如果您不小心,错误处理会变得更加复杂。

答案3

更简单的代码,使用bash关联数组:

declare -A a=([a]=add [d]=delete)
while read username action; do
    ${a[$action]}User ${username}
done < myFile

相关内容