crontab with ed by commands on stream, 结果 "no modification made"
crontab with ed by commands on stream, results in "no modification made"
我正在尝试向我的 crontab 文件追加一行。我知道有其他方法可以解决此问题,但仍想知道是什么原因造成的。命令是 运行 on raspberry pi 3 B+,安装了 raspbian lite,GNU ed 1.15,cron 3.0pl1-134+deb10u1.
我卡住的命令是这样的:
$ echo -e 'a\n#asdf\n.\nwQ' | EDITOR=ed crontab -e
902
909
No modification made
我希望它在我的 crontab 文件末尾添加行 #asdf
,但它没有。
按照 上的建议设置 EDITOR='tee -a'
并不能解决问题。所以我猜是cron的问题。
St运行足够好,当我直接从键盘发出 ed 命令时,而不是流式传输它,它就可以正常工作。也许子外壳创建导致了问题?
我在这里附上 strace
结果的最后几行。
$ echo -e 'a\n#asdf\n.\nwQ' | EDITOR=ed strace crontab -e
execve("/usr/bin/crontab", ["crontab", "-e"], 0x7ee54c14 /* 29 vars */) = 0
access("/etc/suid-debug", F_OK) = -1 ENOENT (No such file or directory)
...
read(3, "TZif2[=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=]"..., 4096) = 659
_llseek(3, -393, [266], SEEK_CUR) = 0
read(3, "TZif2[=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=]"..., 4096) = 393
close(3) = 0
getpid() = 18579
socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/dev/log"}, 110) = 0
send(3, "<78>Nov 20 15:31:25 crontab[1857"..., 56, MSG_NOSIGNAL) = 56
openat(AT_FDCWD, "crontabs/pi", O_RDONLY) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 4
fstat64(4, {st_mode=S_IFREG|0644, st_size=2995, ...}) = 0
read(4, "# Locale name alias data base.\n#"..., 4096) = 2995
read(4, "", 4096) = 0
close(4) = 0
openat(AT_FDCWD, "/usr/share/locale/en_GB.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_GB.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_GB/LC_MESSAGES/libc.mo", O_RDONLY) = 4
fstat64(4, {st_mode=S_IFREG|0644, st_size=1433, ...}) = 0
mmap2(NULL, 1433, PROT_READ, MAP_PRIVATE, 4, 0) = 0x76f50000
close(4) = 0
openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, "crontabs/pi/: fdopen: Permission"..., 39crontabs/pi/: fdopen: Permission denied) = 39
exit_group(1) = ?
+++ exited with 1 +++
openat(AT_FDCWD, "crontabs/pi", O_RDONLY) = -1 EACCES (Permission denied)
看起来有点可疑,但不确定为什么它以只读方式打开文件。
编辑:
正如@tink 所建议的,我 运行 EDITOR=ed strace crontab -e
看看 strace
在交互式会话中给出了什么。结果几乎相同(仅在 pid 和 fd 数字上有所不同)。
我注意到 运行ning echo "..." | EDITOR=ed crontab -e
以消息 No modification made
退出,但是 strace
进程停止,没有任何消息。 (EDITOR=ed strace crontab -e 2>&1 | grep "No mod"
不打印任何内容)。猜测 strace 会触发不同的错误。
根据我的 VISUAL 评论,这些对我有用:
( unset VISUAL; printf '%s\n' a '#abcd' . wq | EDITOR=ed crontab -e )
printf '%s\n' a '#abcd' . wq | VISUAL=ed crontab -e
在我的环境中,VISUAL 和 EDITOR 都设置为“vim”
或者,更迂回,但不需要使用环境变量。这个也可以让你默默地做:
crontab <(printf '%s\n' a '#asdf' . '%p' | ed -s <(crontab -l))
我在 Mac 上执行上述操作。在 Linux,我可以重现你的观察结果,但无法解释它们。
对最后一个命令的小调整有效:
printf '%s\n' a '#asdf' . '%p' Q | ed -s <(crontab -l) | crontab -
TLDR; (sleep 1; echo -e 'a\n#asdf\n.\nwQ') | EDITOR=ed crontab -e
有效!
问题出在 crontab
。
当我调用 crontab -e
时,它会在 /tmp
目录中创建用户 cron table 的临时副本。
然后用 $EDITOR
指定的编辑器打开临时文件。
编辑完成后,crontab
检查文件修改日期自创建后是否发生变化。
这是在 patch 中实现的,它允许通过临时文件编辑 cron table。
在我的例子中,ed
从 stdin
获取命令完成编辑的速度太快,以至于临时文件的修改时间戳甚至没有一个数字被更改。
由于 crontab
考虑到没有人可以如此快速地制作版本,因此它假设没有进行任何修改并丢弃它。
为了绕过这个行为,我在命令发布之前添加了sleep 1
。
这将使 ed
在 crontab
创建临时文件后等待来自 stdin
的命令,这有效地让修改时间戳不同。
我正在尝试向我的 crontab 文件追加一行。我知道有其他方法可以解决此问题,但仍想知道是什么原因造成的。命令是 运行 on raspberry pi 3 B+,安装了 raspbian lite,GNU ed 1.15,cron 3.0pl1-134+deb10u1.
我卡住的命令是这样的:
$ echo -e 'a\n#asdf\n.\nwQ' | EDITOR=ed crontab -e
902
909
No modification made
我希望它在我的 crontab 文件末尾添加行 #asdf
,但它没有。
按照 上的建议设置 EDITOR='tee -a'
并不能解决问题。所以我猜是cron的问题。
St运行足够好,当我直接从键盘发出 ed 命令时,而不是流式传输它,它就可以正常工作。也许子外壳创建导致了问题?
我在这里附上 strace
结果的最后几行。
$ echo -e 'a\n#asdf\n.\nwQ' | EDITOR=ed strace crontab -e
execve("/usr/bin/crontab", ["crontab", "-e"], 0x7ee54c14 /* 29 vars */) = 0
access("/etc/suid-debug", F_OK) = -1 ENOENT (No such file or directory)
...
read(3, "TZif2[=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=]"..., 4096) = 659
_llseek(3, -393, [266], SEEK_CUR) = 0
read(3, "TZif2[=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=][=12=]"..., 4096) = 393
close(3) = 0
getpid() = 18579
socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/dev/log"}, 110) = 0
send(3, "<78>Nov 20 15:31:25 crontab[1857"..., 56, MSG_NOSIGNAL) = 56
openat(AT_FDCWD, "crontabs/pi", O_RDONLY) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 4
fstat64(4, {st_mode=S_IFREG|0644, st_size=2995, ...}) = 0
read(4, "# Locale name alias data base.\n#"..., 4096) = 2995
read(4, "", 4096) = 0
close(4) = 0
openat(AT_FDCWD, "/usr/share/locale/en_GB.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_GB.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_GB/LC_MESSAGES/libc.mo", O_RDONLY) = 4
fstat64(4, {st_mode=S_IFREG|0644, st_size=1433, ...}) = 0
mmap2(NULL, 1433, PROT_READ, MAP_PRIVATE, 4, 0) = 0x76f50000
close(4) = 0
openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, "crontabs/pi/: fdopen: Permission"..., 39crontabs/pi/: fdopen: Permission denied) = 39
exit_group(1) = ?
+++ exited with 1 +++
openat(AT_FDCWD, "crontabs/pi", O_RDONLY) = -1 EACCES (Permission denied)
看起来有点可疑,但不确定为什么它以只读方式打开文件。
编辑:
正如@tink 所建议的,我 运行 EDITOR=ed strace crontab -e
看看 strace
在交互式会话中给出了什么。结果几乎相同(仅在 pid 和 fd 数字上有所不同)。
我注意到 运行ning echo "..." | EDITOR=ed crontab -e
以消息 No modification made
退出,但是 strace
进程停止,没有任何消息。 (EDITOR=ed strace crontab -e 2>&1 | grep "No mod"
不打印任何内容)。猜测 strace 会触发不同的错误。
根据我的 VISUAL 评论,这些对我有用:
( unset VISUAL; printf '%s\n' a '#abcd' . wq | EDITOR=ed crontab -e )
printf '%s\n' a '#abcd' . wq | VISUAL=ed crontab -e
在我的环境中,VISUAL 和 EDITOR 都设置为“vim”
或者,更迂回,但不需要使用环境变量。这个也可以让你默默地做:
crontab <(printf '%s\n' a '#asdf' . '%p' | ed -s <(crontab -l))
我在 Mac 上执行上述操作。在 Linux,我可以重现你的观察结果,但无法解释它们。
对最后一个命令的小调整有效:
printf '%s\n' a '#asdf' . '%p' Q | ed -s <(crontab -l) | crontab -
TLDR; (sleep 1; echo -e 'a\n#asdf\n.\nwQ') | EDITOR=ed crontab -e
有效!
问题出在 crontab
。
当我调用 crontab -e
时,它会在 /tmp
目录中创建用户 cron table 的临时副本。
然后用 $EDITOR
指定的编辑器打开临时文件。
编辑完成后,crontab
检查文件修改日期自创建后是否发生变化。
这是在 patch 中实现的,它允许通过临时文件编辑 cron table。
在我的例子中,ed
从 stdin
获取命令完成编辑的速度太快,以至于临时文件的修改时间戳甚至没有一个数字被更改。
由于 crontab
考虑到没有人可以如此快速地制作版本,因此它假设没有进行任何修改并丢弃它。
为了绕过这个行为,我在命令发布之前添加了sleep 1
。
这将使 ed
在 crontab
创建临时文件后等待来自 stdin
的命令,这有效地让修改时间戳不同。