linux - Ubuntu 20.04.2 和 21.04 之间的不同脚本行为终止
问题描述
可以在 Ubuntu 21.04 上毫无问题地在 shell 脚本中运行以下命令:
grep -h "new tip" logs/node.log | tail -1000 | sed -rn "s/\[(.*)\].\[(.*)\].* ([0-9]+)/\2,\3/p" | awk -F, -v threshold=2 '{"date +%s.%3N -d\""$1"\""|getline actualTime; delay=actualTime-$2-1591566291; sum+=delay; if (delay > threshold ) print $1 " " delay;} END {print "AVG=", sum/NR}'
但是当我在 Ubuntu 20.04.2 上运行完全相同的脚本时,我得到了这个错误:
/bin/sh: 1: Syntax error: Unterminated quoted string
这绝对是完全相同的脚本,因为我从 21.04 到 20.04.2 对它进行了 scp'd。在 stackoverflow 或整个互联网上找不到解决此差异的任何主题。两个 Ubuntu 都在 Linux 云服务器上。关于没有错误运行脚本的唯一方法是取出这一awk
行"date +%s.%3N -d\""$1"\""|getline actualTime
:
我尝试使用对该$1
字段的引用,但没有任何效果。nawk
用代替尝试过awk
,但没有运气。也许作为最后的手段,我可以将操作系统从 v 20 升级到 v 21。
有没有人见过这个?
补充:感谢大家的快速回复。这是脚本运行的日志文件的第一行
[Relaynod:cardano.node.ChainDB:Notice:60] [2021-06-30 02:20:14.36 UTC] 链扩展,新提示:de56b9f458e8942ca74c6a1913dc58fa896823dc19b366285e15481f434ed337 在插槽 33453323 [Relayno] [ChainDB:Noticed:cardano] 2021-06-30 02:20:15.17 UTC] 链延长,新提示:e88ea4f438944bd15186fe93f321c117ec769cfbd33667654634f4510cfd3780 在插槽 33453324
只是为了确保这不是数据问题。我在 Ubuntu 21 服务器上针对文件运行脚本(工作),然后将文件复制到 Ubuntu 20 服务器并针对复制的文件运行完全相同的脚本,并得到错误。
我将尝试有关此主题的建议,并让每个人都知道答案。
新更新:笔记本电脑崩溃和更换后,记得回到这个帖子。我最终像 Ed 提到的那样使用 mktime。它现在正在工作。
外壳脚本:
#!/bin/bash grep -h "新提示" logs/node.log | 尾-1000 | sed -rn "s/[(.)].[(.)].* ([0-9 ] +)/\2,\3/p" | mawk -F, -v 阈值=2 -f check_delay.awk
awk 脚本:
BEGIN{ ENVIRON["TZ"] = "UTC"; }
{
year = substr($1,1,4);
month = substr($1,6,2);
day = substr($1,9,2);
hour = substr($1,12,2);
min = substr($1,15,2);
sec = substr($1,18,2);
timestamp = year" "month" "day" "hour" "min" "sec;
actualTime=mktime(timestamp) + 7200;
delay=actualTime-$2-1591566291;
sum+=delay;
if (delay >= threshold )
print $1 " " delay;}
END {print "AVG=", sum/NR}
解决方案
您正在使用数据date
中恰好包含的任何值生成一个 shell 来调用$1
,因此结果将取决于您的数据。看:
$ echo '3/27/2021' | awk '{"date +%s.%3N -d\""$1"\"" | getline; print}'
1616821200.000
$ echo 'a"b' | awk '{"date +%s.%3N -d\""$1"\"" | getline; print}'
sh: -c: line 0: unexpected EOF while looking for matching `"'
sh: -c: line 1: syntax error: unexpected end of file
a"b
以及此命令从日志文件中输出的内容:
sed -rn "s/\[(.*)\].\[(.*)\].* ([0-9]+)/\2,\3/p"
将根据日志文件中特定行的内容而有很大差异,因为您尝试隔离的部分没有锚定并且.*
在您可能打算使用 s 时使用[^]]*
s。例如:
$ echo '[foo] [3/27/2021] 15 something [probably] happened at line 50'
[foo] [3/27/2021] 15 something [probably] happened at line 50
$ echo '[foo] [3/27/2021] 15 something [probably] happened at line 50' | sed -rn "s/\[(.*)\].\[(.*)\].* ([0-9]+)/\2,\3/p"
3/27/2021] 15 something [probably,50
$ echo '[foo] [3/27/2021] 15 something [probably] happened at line 50' | sed -rn "s/\[(.*)\].\[(.*)\].* ([0-9]+)/\2,\3/p" | awk -F, -v threshold=2 '{"date +%s.%3N -d\""$1"\""|getline actualTime; delay=actualTime-$2-1591566291; sum+=delay; if (delay > threshold ) print $1 " " delay;} END {print "AVG=", sum/NR}'
date: invalid date ‘3/27/2021] 15 something [probably’
AVG= -1591566341
如果你想这样做,那么你可以引入一个有效日期检查以避免特定的错误,例如(但显然创建一个比这更好的日期验证正则表达式):
$ echo 'a"b' | awk '$1 ~ "[0-9]/[0-9]+/[0-9]" {"date +%s.%3N -d\""$1"\"" | getline; print}'
$
但它仍然很脆弱并且非常缓慢。
您正在使用 GNU sed,-r
因此您拥有或可以获得 GNU awk 并且具有内置时间函数,因此您不应该首先生成子外壳来调用 date,您应该只是使用mktime()
,请参阅https://stackoverflow .com/a/68180908/1745001,这将避免这样的神秘错误,并且运行速度更快几个数量级。
推荐阅读
- java - 从 Lua 脚本返回集
- css - 在css中自动左右对齐图像
- javascript - 我选择的图像未出现在预览中
- http - gunicorn - 禁用 HTTP OPTION 方法
- reactjs - React 功能组件 - 使用获取的数据时,得到的错误数据不足
- java - Tabula Py 在 Windows 中窃取焦点
- flutter - Flutter 通过 API 登录
- javascript - 无法从 github 安装 ot.js 库
- php - Laravel 8: InvalidArgumentException: Auth guard [admin] 未定义
- ansible - 在 hosts.yaml 文件中创建的分组中执行 playbook