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 命令上的 &lt;/dev/null 阻止它使用标准输入本身,从而导致项目被跳过。 我注意到该值被分配给名为 LINE 的变量,但随后从名为 i 的变量中读取。【参考方案2】:

这里有两个问题:

您在本地打开 /tcb/files/auth/x/xyz,而不是在远程系统上。 sudo echo foo &gt; bar提供额外的权限来帮助打开bar

后者是因为something &gt; 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/xyztee 打开,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循环在创建文件时出错[重复]的主要内容,如果未能解决你的问题,请参考以下文章

将数据从CSV转换为numpy数组时出错

Django ORM - 检索数据时出错 -

使用带有 JavaScript 的 for 循环时,将新列表项添加到 <ul> 项 [重复]

Android “只有创建视图层次结构的原始线程才能接触其视图。” for循环中的错误[重复]

C# - 在for循环中使用相同的列表大小,索引超出了数组的范围[重复]

使用javascript for循环创建金字塔[重复]