[注意:这个类似的 Q涉及相同的 bash 错误消息。它被标记为另一个 Q的副本。但是因为我发现这个错误的来源非常不同,我将在下面回答我自己的问题。]
这个以前工作的 bash 脚本行
while ... do ... done <<< "$foo"
Run Code Online (Sandbox Code Playgroud)
有一天开始产生此错误消息:
无法为此处文档创建临时文件:权限被拒绝
poweroff抱怨它无法通过 DBus 连接到 systemd(当然,它不是活的)。我确实sync紧随其后kill $$,认为 pid 1 死亡会提示内核断电,但这导致内核恐慌。然后我按住电源按钮强制关机。
在这种情况下最合适的关机方式是什么?
有没有办法让open()文件缩小?当然,可以在追加模式下打开它们或寻找到最后并写入以导致它们增长。但是,据我所知,没有办法通过典型的 Unix 风格的系统调用接口来缩小文件。
据我所知,唯一的方法是通过创建一个新的较短的文件并rename()代替旧文件来伪造它。
我只是想确认一下,因为我看到一个答案暗示可以制作直接处理文件的文件编辑器,而不是经历制作新文件并在适当位置重命名的过程。
我一直认为 libc 和 unix 风格的系统调用接口中的文件 api 不允许缩小文件以简化文件系统的实现,并可能避免可能导致碎片化的使用模式。
我一直认为 shell 会解析整个脚本,构建一个 AST,然后从内存中执行该 AST。但是,我刚刚阅读了 Stéphane Chazelas 的评论,并测试了执行此脚本 edit-while-executing.sh:
#!/bin/bash
echo start
sleep 10
Run Code Online (Sandbox Code Playgroud)
然后在它睡觉的时候运行:
$ echo "echo end" >> edit-while-executing.sh
Run Code Online (Sandbox Code Playgroud)
它的作用是让它在最后打印“结束”。
但是,当尝试修改它时:
#!/bin/bash
while true; do
echo yes
done
Run Code Online (Sandbox Code Playgroud)
通过做:
$ printf "%s" "no " | dd of=edit-while-executing.sh conv=notrunc seek=35 bs=1
Run Code Online (Sandbox Code Playgroud)
它不起作用,并继续打印“是”。
我还想知道其他非 shell 解释器是否也这样工作,并尝试使用 python 执行与第一个脚本等效的操作,但没有奏效。不过,也许 python 不再是解释器,它更像是一个 JIT 编译器。
所以重申我的问题,这是一种普遍存在于 shell 并仅限于它们的行为,还是也存在于其他解释器中(那些不被视为 shell 的)?另外这是如何工作的,以便我可以进行第一次修改而不是第二次修改?
我想我可以做这样的事情:
\nsudo unshare -T bash -c \'date -s "$1" && foobar\' sh "$(date -d -1day)"\nRun Code Online (Sandbox Code Playgroud)\n所以foobar会看到与系统其他部分不同的系统时间。但是,似乎不包含系统时间的变化。它改变了整个系统的系统时间。
这篇 LWN 文章似乎表明这个命名空间是为了我试图赋予它的用途而设计的。
\n\n\n当在根时间命名空间之外调用时,调整系统时间的系统调用将调整特定于命名空间的偏移量。
\n
看着strace date -s ...,我看到了其他输出:
clock_settime(CLOCK_REALTIME, {tv_sec=1619044910, tv_nsec=0}) = 0\nRun Code Online (Sandbox Code Playgroud)\n然而,阅读time_namespaces(7):
\n\n这会影响针对这些时钟进行测量的各种 API,包括:clock_gettime(2)、clock_nanosleep(2)、nanosleep(2)、timer_settime(2)、timerfd_settime(2) 和 /proc/uptime。
\n
我看到它没有提到clock_settime(2)。“包括”一词告诉我这可能不是完整的列表,但也许是。
我也不懂--boottime/ --monotonic。看着clock_settime(2),我看到:
\n\nCLOCK_MONOTONIC 不可设置的系统范围时钟,表示自 \xe2\x80\x94 以来的单调时间,如 POSIX\xe2\x80\x94 所描述的“过去的某个未指定点”。在 Linux 上,该点对应于系统自启动以来运行的秒数。
\n
\nCLOCK_BOOTTIME(自 Linux …
这是一个后续问题:为什么`... | sed 's/^/stdout: /'` 当`... > >(sed 's/^/stdout: /')` 不打印在空的标准输入上?
更具体地说,为什么这是一个管道:
$ tee 2> >(readlink /proc/self/fd/1) < /dev/null | cat
pipe:[17955449]
Run Code Online (Sandbox Code Playgroud)
当这是终端设备时?:
$ tee >(readlink /proc/self/fd/1) < /dev/null | cat
/dev/pts/31
Run Code Online (Sandbox Code Playgroud)
我原以为前者的输出也自然是从我输入命令的 shell 继承的终端,但似乎 bash 和 zsh 都必须采取明确的步骤将其重定向到命令的输出他们正在重定向。他们为什么这样做?还是发生了其他事情?前者的子shelltee是在exec'ing之前从's 进程产生的tee吗?一个子shell是否从子进程继承而另一个从父进程继承?如何?
嗯...在做标签和检查时bash,我发现这两种情况都是 bash 中的管道...所以这是 zsh 的特性。
我有一个 SSD,有 2 个分区,格式为 ext4。在第二个分区上,我使用discard以下命令在文件系统级别启用了默认选项:
$ sudo tune2fs -o discard /dev/sda2
tune2fs 1.45.5 (07-Jan-2020)
$ sudo tune2fs -l /dev/sda2 | grep 'mount options'
Default mount options: user_xattr acl discard
Run Code Online (Sandbox Code Playgroud)
我还在discard两个分区上添加了该选项/etc/fstab:
/dev/sda2 / ext4 rw,relatime,discard,stripe=8191 0 1
/dev/sda1 /boot ext4 rw,relatime,discard,stripe=8191 0 2
Run Code Online (Sandbox Code Playgroud)
然而,当我查看 的输出时mount,只有没有discardfs-level 默认挂载选项的输出似乎启用了它:
$ mount | grep '^/dev'
/dev/sda2 on / type ext4 (rw,relatime,stripe=8191)
/dev/sda1 on /boot type ext4 (rw,relatime,discard,stripe=8191)
Run Code Online (Sandbox Code Playgroud)
我注意到提到的其他选项tune2fs也没有提及。
那么,尽管没有提及,我可以相信discard当前安装中已启用该功能吗?有什么方法可以验证吗?我的意思是, Even的输出与当前安装无关。/dev/sda2 …
linux ×3
bash ×1
clock ×1
e2fsprogs ×1
ext4 ×1
files ×1
filesystems ×1
here-string ×1
interpreter ×1
namespace ×1
permissions ×1
shell ×1
shell-script ×1
ssd ×1
systemd ×1
unshare ×1
util-linux ×1
zsh ×1