Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 命令脚本返回";太多了;_Bash - Fatal编程技术网

Bash 命令脚本返回";太多了;

Bash 命令脚本返回";太多了;,bash,Bash,下面的脚本是我在RHEL 5上构建的,它运行得很好。但是现在我在各种RHEL 6和Ubuntu上进行测试,消息是一致的“太多('s.)。有什么想法吗?这就是我正在编写的脚本 $ echo "HOST,UserName,IsDiabled,PassLastSet" > fileIWantToWriteTo; $ ( echo "foreach user ( `cut -d':' -f'1' /etc/passwd` )"; echo "sudo passwd -S "\$"user"

下面的脚本是我在RHEL 5上构建的,它运行得很好。但是现在我在各种RHEL 6和Ubuntu上进行测试,消息是一致的“太多('s.)。有什么想法吗?这就是我正在编写的脚本

$ echo "HOST,UserName,IsDiabled,PassLastSet" > fileIWantToWriteTo;
$ ( echo "foreach user ( `cut -d':' -f'1' /etc/passwd` )";
    echo "sudo passwd -S "\$"user" ; echo "end"
  ) | csh | 
  sed 's/ /,/g' | cut -f1-3 -d',' | 
  sed 's/LK/DISABLED/' | 
  sed 's/PS/ENABLED/' | 
  awk 'BEGIN{"hostname" | getline hstnm ; }{print hstnm "," $0}' \
    >> fileIWantToWriteTo
现在,我正在各种Linux操作系统上测试它,并得到以下输出消息

# ( echo "foreach user ( `cut -d':' -f'1' /etc/passwd` )"
echo "sudo passwd -S "\$"user" ; echo "end" ) | 
csh | 
sed 's/ /,/g' | 
cut -f1-3 -d',' | 
sed 's/LK/DISABLED/' | 
sed 's/PS/ENABLED/' | 
awk 'BEGIN{"hostname" | getline hstnm ; }; {print hstnm "," $0}'
Too many ('s.
然而,当我在测试时,我成功了

# ( echo "foreach user ( `cut -d':' -f'1' /etc/passwd` )"
echo "sudo passwd -S "\$"user" ; echo "end" ) | 
csh | 
sed 's/ /,/g' | 
cut -f1-3 -d',' | 
sed 's/LK/DISABLED/' | 
sed 's/PS/ENABLED/' | 
awk 'BEGIN{"hostname" | getline hstnm ; }; {print hstnm "," $0}'
tophostd,root,ENABLED,2015-08-31 tophostd,bin,DISABLED,2013-08-19

我的猜测是,当您测试该命令行时,列表中只有一个用户id

简化脚本 使用bash创建一个复合命令发送到
csh
给我的印象是故意混淆或奇怪的过度思考,而不是不起作用

( echo "foreach user ( `cut -d':' -f'1' /etc/passwd` )"
  echo "sudo passwd -S "\$"user" ; echo "end"
) | csh |
# ...
你可以这样做:

for user in $(cut -d: -f1 /etc/passwd); do
  sudo passwd -S $user
done
完全不需要csh,而且阅读起来也容易得多。另外,它还能工作。(它确实假设用户名中不包含空格或全局字符。)

更简单的是

sudo passwd -Sa
它生成所有帐户的状态信息。(假设您的
passwd
实现了该选项。)

此外:

可能会更容易阅读

cut -f1-3 --output-delimiter=,
以及两次编辑

sed 's/LK/DISABLED/' | sed 's/PS/ENABLED/' 
可以放入单个命令中:

sed 's/LK/DISABLED/;s/PS/ENABLED/'
您还可以使用sed插入前缀

hostname=$(hostname)
sed "s/^/$hostname,/;s/LK/DISABLED/;s/PS/ENABLED/"
所以最终的结果是

hostname=$(hostname)
sudo passwd -Sa |
cut -d' ' --output-delimiter=, -f1-3 |
sed "s/^/$hostname,/;s/LK/DISABLED/;s/PS/ENABLED/"
在我看来,这要简单得多。或者,您可以使用
awk
而不是
cut
+
sed

sudo passwd -Sa |
awk -v hostname="$(hostname)" \
  '{ sub(/LK/, "DISABLED", $2);
     sub(/PS/, "ENABLED", $2);
     printf "%s,%s,%s,%s\n", hostname, $1, $2, $3;
   }'
但回到问题上来 无论如何,脚本失败的原因是:

csh
对于命令格式非常具体。它不允许在意外的地方出现换行符。foreach语句的语法正好是:

foreach <var> ( <list> )
  <commands>
end
但如果有多行,则最终会出现内部换行:

$ echo "foreach i ( $(seq 1 2) )"
foreach i ( 1
2 )
第一个很好,但是如果你把第二个输入到
csh
,它会抱怨有点神秘的信息“太多了”

您可以通过对行进行分词来消除内部换行符,这意味着不使用引号(但仍需要引用括号)


不过,您需要确保替换中没有glob元字符,因为不带引号的替换也会扩展glob。总的来说,我会坚持本答案第一部分中概述的方法,并避免将命令组装到另一个shell中的困难。

我猜当您测试在命令行中,列表中只有一个用户id

简化脚本 使用bash创建一个复合命令发送到
csh
给我的印象是故意混淆或奇怪的过度思考,而不是不起作用

( echo "foreach user ( `cut -d':' -f'1' /etc/passwd` )"
  echo "sudo passwd -S "\$"user" ; echo "end"
) | csh |
# ...
你可以这样做:

for user in $(cut -d: -f1 /etc/passwd); do
  sudo passwd -S $user
done
完全不需要csh,而且阅读起来也容易得多。另外,它还能工作。(它确实假设用户名中不包含空格或全局字符。)

更简单的是

sudo passwd -Sa
它生成所有帐户的状态信息。(假设您的
passwd
实现了该选项。)

此外:

可能会更容易阅读

cut -f1-3 --output-delimiter=,
以及两次编辑

sed 's/LK/DISABLED/' | sed 's/PS/ENABLED/' 
可以放入单个命令中:

sed 's/LK/DISABLED/;s/PS/ENABLED/'
您还可以使用sed插入前缀

hostname=$(hostname)
sed "s/^/$hostname,/;s/LK/DISABLED/;s/PS/ENABLED/"
所以最终的结果是

hostname=$(hostname)
sudo passwd -Sa |
cut -d' ' --output-delimiter=, -f1-3 |
sed "s/^/$hostname,/;s/LK/DISABLED/;s/PS/ENABLED/"
在我看来,这要简单得多。或者,您可以使用
awk
而不是
cut
+
sed

sudo passwd -Sa |
awk -v hostname="$(hostname)" \
  '{ sub(/LK/, "DISABLED", $2);
     sub(/PS/, "ENABLED", $2);
     printf "%s,%s,%s,%s\n", hostname, $1, $2, $3;
   }'
但回到问题上来 无论如何,脚本失败的原因是:

csh
对于命令格式非常具体。它不允许在意外的地方出现换行符。foreach语句的语法正好是:

foreach <var> ( <list> )
  <commands>
end
但如果有多行,则最终会出现内部换行:

$ echo "foreach i ( $(seq 1 2) )"
foreach i ( 1
2 )
第一个很好,但是如果你把第二个输入到
csh
,它会抱怨有点神秘的信息“太多了”

您可以通过对行进行分词来消除内部换行符,这意味着不使用引号(但仍需要引用括号)


不过,您需要确保替换中没有glob元字符,因为不带引号的替换也会扩展glob。总的来说,我将坚持本答案第一部分中概述的方法,并避免将命令组合到另一个shell中的困难。

您的代码几乎难以辨认。请参见ase将其拆分成几行,正确缩进,并使用“{}”链接将其格式化为代码。@davidRanking感谢您的编辑。我开始并放弃了;)不鼓励将一个理解不透彻的命令的输出管道化为另一个理解不透彻的命令。如果您使用
awk
,您可以省去
cut
sed
。如果这是
bash
问题,为什么要将内容管道化到
csh
?您的代码几乎难以辨认。请将它编辑成行,正确缩进,并使用“{}”链接将其格式化为代码。@DavidCRanking这一编辑值得称赞。我开始并放弃了;)不鼓励将一个理解不透彻的命令的输出通过管道传输到另一个理解不透彻的命令。如果您仍然使用
awk
,您可以省去
cut
sed
。如果这是
bash
问题,为什么要将内容传输到
csh