bash - 远程运行与本地运行时,Bash while 循环的行为不同
问题描述
有一个简单的日志文件 /tmp/test.log
2019-12-09 15:28:12 UTC [6308] App1
2019-12-09 15:29:08 UTC [1246] App2
2019-12-09 15:30:57 UTC [5541] App3
有一个简单的 bash 脚本 /tmp/test.sh
#!/bin/bash
#
while read line
do
echo $line
done < /tmp/test.log
如果我在本地运行此脚本,它将按预期工作:
$ /tmp/test.sh
2019-12-09 15:28:12 UTC [6308] App1
2019-12-09 15:29:08 UTC [1246] App2
2019-12-09 15:30:57 UTC [5541] App3
但是如果我通过 ssh 运行这个脚本,我会得到一些意想不到的东西:
$ ssh 127.0.0.1 "/tmp/test.sh"
2019-12-09 15:28:12 UTC 0 3 App1
2019-12-09 15:29:08 UTC 1 App2
2019-12-09 15:30:57 UTC 1 App3
有人知道为什么吗?
解决方案
我认为这里有几个不同的东西相互作用导致了令人困惑的结果。这是我最好的猜测解释。
您对重要 IFS 变量的值可能是 20 09 0a
(这些是十六进制代码,用于空格、制表符、换行符)。这对echo
(以及read
陈述)有重要影响。(用于echo -n "$IFS" | hexdump
查看值)。
该read
命令将从文件中读取每一行,并将它们全部添加到
line
变量中。它实际上会对每一行进行标记,并将每个单词添加到
line
.
该echo
语句将导致对 中的值进行评估line
。shell 将使用IFS
将值分隔为单独的标记,然后将它们全部传递给 echo,echo 将打印它们,用空格分隔。即,有一个很难观察到的外壳预处理步骤。
像 etc 这样的标记会出现问题[6308]
。方括号用于 shell globbing,因此当 bash 遇到类似的东西时,[6308]
它会尝试将其与当前目录中名为 like 6
or 3
or 0
or
的文件匹配8
。因此,如果您有两个名为0
and的文件3
,它将同时匹配它们并返回字符串0 3
。
在本地运行而不是通过 ssh 运行时得到不同结果的原因可能只是由于调用脚本的当前工作目录。通过 ssh 运行时,它不会从您的本地当前目录运行。要查找用于 ssh 调用的 cwd,只需pwd
在文件顶部附近放置一个。我猜测通过 ssh 调用使用的目录具有名为0
etc的文件。
简单的解决方法是防止 shell 处理 的内容$line
,方法是用引号将其括起来,如 echo "$line"
. 您也可以调整 IFS,但引用字符串是通常的做法。
推荐阅读
- mongodb - 模型、视图、控制器、服务、存储库设计模式(RestEasy + MongoDB)
- javascript - 我的函数返回 NaN,我不知道为什么
- javascript - js数字从高到低排序
- html - 悬停水平div时如何保持滚轮垂直滚动?
- python - 如何在 Pandas 中使用 Groupby() 回填和转发对应于每个月的开始和结束的填充值
- java - 如何在工具栏Android中居中按钮
- prolog - Prolog:例如,X 是 3 和 3 是 X 有什么区别?
- database - 使用 WhiteDB 的图形数据库
- ansible - Ansible,如何链接 regex_replace 语句?
- python - Python:从数据集中创建 5-6 个组,以便这些组在 3 个不同的变量(十分位数、人口规模和区域)之间保持平衡