语法错误源行为1

时间:2016-02-18 15:22:34

标签: linux bash unix redirect scripting

我在主机列表文件中有一个服务器列表,我正在尝试执行以下脚本:

!/bin/bash
for server in cat hostlist; do ssh $server 'hostname ;id $(cat /etc/passwd | grep Luyang | awk -F '[:]' '{print $1}') ; id ppandey' >> b done

我想获取用户Luyang的id命令的输出。对于我提到的id $(cat /etc/passwd | grep Luyang | awk -F '[:]' '{print $1}'),我在运行脚本时遇到错误。我也尝试在所有特殊字符前加上'\',但没有运气。

2 个答案:

答案 0 :(得分:0)

这里有很多问题:

  • 第一行需要#作为正确的shebang行(即#!/bin/bash)。
  • for server in cat hostlist将运行循环两次,一次将$ server设置为“cat”,然后将其设置为“hostlist”。您希望将cat hostlist作为命令执行并使用其输出,即for server in $(cat hostlist)

    实际上,根据文件的确切格式和内容,while read -u3 server; do ... done 3<hostfile可能会更好,但for版本可能已经足够好了。 (不同之处在于for将文件分成单词,而不是行,并将任何通配符展开,就像它们是文件名一样。我不希望这里有任何问题。)

  • 你不能按照你想要的方式嵌套引号。当您使用单引号字符串(如'hostname ;id ... ; id ppandey')时,中间的任何单引号都将作为单引号字符串的结尾,而不是其中的一部分。我将切换到使用双引号作为外部集合,然后转义$内部以防止它们被解释。
  • cat|grep|awk过于复杂,因为awk可以直接从文件中读取并自行搜索。只需使用awk -F : '/Luyang/ {print $1}' /etc/passwd
  • 您需要在done之前使用分号或换行符。就个人而言,我认为将循环转换为逻辑行会使它们更容易阅读,所以我会继续使用它。
  • 最后,您可能希望使用文件主机列表和b的绝对路径。实际上,它会查看启动脚本的任何进程的工作目录,这可能是任何事情。您应该假设它是脚本所在的目录。

这是我得到的整体(绝对路径除外)。请注意,我还引用了"$server",只是基于一般原则。

#!/bin/bash
for server in $(cat hostlist); do
    ssh "$server" "hostname; id \$(awk -F : '/Luyang/ {print \$1}' /etc/passwd); id ppandey" >> b
done

答案 1 :(得分:-2)

将你的cat命令放在$()和;之间;在append命令之后。

!/bin/bash
for server in $(cat hostlist); do ssh $server 'hostname ;id $(cat /etc/passwd | grep Luyang | awk -F '[:]' '{print $1}') ; id ppandey' >> b; done