【问题标题】:Bash reading from file and parsing each line [duplicate]Bash从文件中读取并解析每一行[重复]
【发布时间】:2014-05-30 00:52:20
【问题描述】:

我需要在多个客户的 linux 服务器上管理特定软件的更新。更新是通过将 .tar.gz 文件发送到每个服务器并对其进行膨胀覆盖旧软件文件来提供的。

我已将客户的服务器列表放在一个 txt 文件中,如下所示:

user1@customer-server-1-address:22:/path/to/software/server1:NULL:Customer1name

user2@customer-server-2-address:2222:/path/to/software/server2:/etc/vpnc/client1.conf:Customer2name

user3@customer-server-3-address:22:/path/to/software/server3:NULL:Customer3name

Char ":" 充当字段分隔符;字段 1 是服务器地址,2 是端口,3 是软件路径,4 用于判断是否要先启用 VPN 隧道,5 是客户名称。

我已经设法创建了以下脚本:

#!/bin/bash

[...]

while IFS=':' read -ra array; do
    if [ "${array[3]}" != "NULL" ]; then
        echo
        echo "### USING VPN CONF '${array[3]}' FOR SERVER '${array[0]}'... ###"
        sleep 1
        #vpnc ${array[3]}
        TUNNEL1=$(ifconfig | grep -o eth0)
        TUNNEL2='eth0'

        if [ "$TUNNEL1" = "$TUNNEL2" ]; then
          echo "### TUNNEL IS UP ###"

          scp -P${array[1]} $FILENAME.gz ${array[0]}:${array[2]}
          scp -P${array[1]} $FILELIST ${array[0]}:${array[2]}

          ssh -p${array[1]} ${array[0]} 'cd '${array[2]}' && cat '${array[2]}'/'$FILELIST' | cpio --quiet -H ustar -o -0 -L -F '${array[2]}'/'$BACKUP_FILENAME
          ssh -p${array[1]} ${array[0]} 'gzip '${array[2]}'/'$BACKUP_FILENAME

          ssh -p${array[1]} ${array[0]} 'tar -C '${array[2]}' -xf '${array[2]}'/'$FILENAME.gz
          ssh -p${array[1]} ${array[0]} 'cd '${array[2]}' && mkdir -p '$REMOTE_BACKUP_DIRECTORY' && rm -f '$FILELIST' && mv -f '$BACKUP_FILENAME.gz $REMOTE_BACKUP_DIRECTORY

          echo "### SERVER '${array[0]}' UPDATED ###"
          #vpnc-disconnect
          sleep 1
        else
          echo "### VPN ERROR IN SERVER '${array[4]}' ###"
        fi
    else
        echo

        scp -P${array[1]} $FILENAME.gz ${array[0]}:${array[2]}
        scp -P${array[1]} $FILELIST ${array[0]}:${array[2]}

        ssh -p${array[1]} ${array[0]} 'cd '${array[2]}' && cat '${array[2]}'/'$FILELIST' | cpio --quiet -H ustar -o -0 -L -F '${array[2]}'/'$BACKUP_FILENAME-${array[4]}
        ssh -p${array[1]} ${array[0]} 'gzip '${array[2]}'/'$BACKUP_FILENAME-${array[4]}

        ssh -p${array[1]} ${array[0]} 'tar -C '${array[2]}' -xf '${array[2]}'/'$FILENAME.gz

        ssh -p${array[1]} ${array[0]} 'cd '${array[2]}' && mkdir -p '$REMOTE_BACKUP_DIRECTORY' && rm -f '$FILELIST' && mv -f '$BACKUP_FILENAME-${array[4]}.gz $REMOTE_BACKUP_DIRECTORY

        echo "### SERVER '${array[4]}' UPDATED ###"
        echo
    fi;
done < "$CUSTOMER_SERVERS_FILE"

$CUSTOMER_SERVERS_FILE 是前面描述的容器文件,$FILENAME.gz 是更新包, $FILELIST 是要更新的文件的列表。为其他目的而设置的其他变量。

问题是,整个过程为我的 $CUSTOMER_SERVERS_FILE 中的第一个客户有效地运行。第一行上面的行被跳过了,我不知道为什么。有什么提示吗?谢谢。

编辑:作为对重复反对意见的回答,由于脚本相当大,我没有想到 whilessh 之间有任何联系em> 对象。我宁愿更多地考虑语法错误。但是,如果被要求删除问题,我仍然可以这样做。

【问题讨论】:

  • 简化问题,让它做一件事情,这样你就可以找出循环错误的原因。即是 while 循环中的问题还是代码主体中的某个地方......将问题分解为更小的问题,看看你卡在哪里以及为什么。
  • 专业提示:我刚刚注意到删除所有“ssh”行解决了,但我仍然不知道为什么这不起作用
  • 所以尝试一次添加一个,看看你会卡在哪一个...
  • 第一个已经足够破解了。但我仍然真的不知道为什么......
  • 好剧本。你做的不错。 stdin for while 和 ssh 是一个高级问题。继续插电。祝大家好运。

标签: linux bash


【解决方案1】:

这是因为您的 while read 循环和 ssh 都从标准输入读取。

您可以使用/dev/null 作为ssh 的标准输入来修复它:

ssh host cmd  < /dev/null 

【讨论】:

  • 还有ssh -n host cmd
  • 就是这样!非常感谢,我自己永远也做不到。我觉得我永远不会对 bash 脚本有足够的了解......
猜你喜欢
  • 2014-12-17
  • 2023-04-03
  • 2014-01-02
  • 2021-05-16
  • 1970-01-01
  • 2017-07-04
  • 1970-01-01
  • 2018-05-03
  • 2013-03-07
相关资源
最近更新 更多