For循环在创建文件时出错[重复]
Posted
技术标签:
【中文标题】For循环在创建文件时出错[重复]【英文标题】:For loop giving error while creating file [duplicate] 【发布时间】:2017-08-20 10:46:47 【问题描述】:我对 for 循环有疑问。会为你简述。
$ for i in `cat serverss`;do ssh -q $i sudo echo "a b c" > /tcb/files/auth/x/xyz;done
ksh: /tcb/files/auth/x/xyz: cannot create
每当我尝试创建或修改文件时,我都会遇到上述错误。 serverss 是包含服务器列表的文件文件。我们在这些系统上使用 sudo 进行 root。
问题是当我在单个服务器上运行 echo "a b c" > /tcb/files/auth/x/xyz
时,它运行良好。我的 for 循环中出现上述错误的问题是什么。
【问题讨论】:
for
循环本身根本不是问题;这是如何给出ssh
的参数的问题。 ssh -q $i sudo echo "a b c" > /tcb/files/auth/x/xyz
根本不在任何 for
循环内,您也会遇到同样的问题。
还有一点是sudo echo
是没用的:它提升了echo
的权限(就是写到stdout),不是shell打开@的权限987654329@.
【参考方案1】:
你的命令被破坏了。它远程执行sudo echo "a b c"
,并尝试将标准输出重定向到不存在的本地文件/tcb/files/auth/x/xyz
。
您应该以某种方式将其括起来,例如:
$ for i in `cat serverss`;do ssh -q $i "sudo echo 'a b c' > /tcb/files/auth/x/xyz";done
或者@CharlesDuffy 可能会喜欢:
$ while read -r line; do ssh -q $line "sudo echo 'a b c' > /tcb/files/auth/x/xyz";done < serverss
【讨论】:
这确实违反了DontReadLinesWithFor,但是原来的也违反了。 顺便说一句,不,这 不是 我更喜欢;对于对操作系统或 shell 有意义的变量,全大写变量名是 reserved by POSIX convention。 (请记住,设置常规 shell 变量将覆盖任何类似命名的环境变量) 我曾尝试在cat serverss
中为 i 提到双引号;do ssh -q $i "sudo echo 'a b c' > /tcb/files/auth/x/xyz";done。但仍然没有运气。同样的错误
一些笔记。在 while read
循环中,您需要 ssh 命令上的 </dev/null
阻止它使用标准输入本身,从而导致项目被跳过。
我注意到该值被分配给名为 LINE
的变量,但随后从名为 i
的变量中读取。【参考方案2】:
这里有两个问题:
您在本地打开/tcb/files/auth/x/xyz
,而不是在远程系统上。
sudo echo foo > bar
不提供额外的权限来帮助打开bar
。
后者是因为something > output
打开output
之前它运行something
。因此,sudo
在打开/tcb/files/auth/x/xyz
时甚至还没有启动!
相反,请考虑:
ssh -q "$i" 'echo "a b c" | sudo tee /tcb/files/auth/x/xyz >/dev/null'
第一个问题解决了,因为重定向在传递给ssh
的字符串内,由远程shell 运行。 (如果你传递ssh
一堆单独的参数,它只是将它们与空格结合起来形成这样的字符串;最好自己形成字符串,从而有更多的控制权)。
第二个问题通过强制/tcb/files/auth/x/xyz
由tee
打开,tee
的权限已被sudo
升级来解决。
【讨论】:
谢谢查尔斯,它成功了。实际上,我尝试在我的 sed 替换中使用 tee,例如 ssh -q abc "sed -e 's/\:u_pwd.*/\:u_pwd\=np\:\\/p' /tcb/files/auth/a /abcde.tmp | sudo tee /tcb/files/auth/a/abcde >/dev/null" 它清空我的文件,因为您知道 sed -i 选项在 KSH 中不起作用我制作了文件的副本 sed on它并将其定向到像这样的原始文件 sed -e 's/\:u_pwd.*/\:u_pwd\=np\:\\/p' /tcb/files/auth/a/abcde.tmp >/tcb/文件/身份验证/a/abcde。我的观点是 echo 你建议使用 tee 而不是 > 所以对于 sed 我可以使用什么作为 tee 似乎没有做我的工作。 其实不是ksh-vs-bash;sed -i
是否有效取决于您拥有的sed
版本,而不是您使用的shell。也就是说,由于您已经在输入和输出中使用了不同的文件名,所以应该这样做——我建议确保 sed
命令按预期工作。 ssh -q abc "sed -e 's/\:u_pwd.*/\:u_pwd\=np\:\\/p' /tcb/files/auth/a/abcde.tmp"
真的有你想要的输出吗?如果没有,我建议使用set -x
-- 如,`ssh -q abc "set -x; sed -e 's/\:u_pwd.*/\:u_pwd\=np\:\\/p ' /tcb/files/auth/a/abcde.tmp"`` -- 进行调试。
是的,我在许多服务器上测试过我的 sed 作品。 sed 's/\:u_pwd.*/\:u_pwd\=NP\:\\/p' /tcb/files/auth/a/abcde.tmp > /tcb/files/auth/a/abcde.关键是 sed 命令上面的 Sir 可以在单个服务器上正确运行,但是当添加到服务器列表的 for 循环中时,它会失败。它引发以下错误(ksh:/tcb/files/auth/a/abcde:无法创建)。我也有命令的双引号,但没有运气。至于现在,我可以使用您建议的带有 echo 的 tee 命令创建文件,但我不确定是否要修改 for 循环中的任何文件。谢谢
不仅仅是sed
是否有效,而是它是否以您引用它的特定方式在ssh 之后 有效。我不太相信您评论中的引用-您正在转义不需要需要转义的字符;有时这可能会产生不幸的副作用,具体取决于已实施的标准扩展。
您好先生,您是对的,SED 的行为在 SSH 上完全不同。根据您的建议,我重新设计了我的 sed 替换并提出了 ssh -q abc sed -e 's/:u_pwd.*/:u_pwd=Lp:\\/g' /tcb/files/auth/a/abcde | sudo tee /tcb/files/auth/a/abcde 会引发错误 sed: Function s/:u_pwd.*/:u_pwd=Lp:\/g cannot be parsed here in the error。我在这里注意到的是 SSH 中 sed 未使用的第二个 \ 并引发相同的错误。以上是关于For循环在创建文件时出错[重复]的主要内容,如果未能解决你的问题,请参考以下文章
使用带有 JavaScript 的 for 循环时,将新列表项添加到 <ul> 项 [重复]
Android “只有创建视图层次结构的原始线程才能接触其视图。” for循环中的错误[重复]