我正在阅读一个示例 bash shell 脚本:
#!/bin/bash
# This script makes a backup of my home directory.
cd /home
# This creates the archive
tar cf /var/tmp/home_franky.tar franky > /dev/null 2>&1
# First remove the old bzip2 file. Redirect errors because this generates some if the archive
# does not exist. Then create a new compressed file.
rm /var/tmp/home_franky.tar.bz2 2> /dev/null
bzip2 /var/tmp/home_franky.tar
# Copy the file to another host - we have ssh keys for making this work without intervention.
scp …Run Code Online (Sandbox Code Playgroud) 我试图了解 Linux 上特殊文件的概念。然而,/dev根据我的知识,当它的功能可以通过 C 中的几行代码实现时,在其中包含一个特殊文件似乎很愚蠢。
此外,您可以以几乎相同的方式使用它,即通过管道进入null而不是重定向到/dev/null. 将其作为文件是否有特定原因?使它成为一个文件不会导致许多其他问题,例如太多程序访问同一文件吗?
我读过,因为 Bash 中的文件路径可以包含除空字节(零值字节$'\0')之外的任何字符,所以最好使用空字节作为分隔符。例如,如果将 的输出find发送到另一个程序,则建议使用该-print0选项(对于find具有它的版本)。
但是,虽然这样的事情工作正常(打印由换行符分隔的文件路径 - 别担心,这只是一个演示,我实际上并没有在实际脚本中这样做):
find -print0 \
| while IFS= read -r -d $'\0' ; do echo "$REPLY" ; done
Run Code Online (Sandbox Code Playgroud)
这样的事情就不会工作:
for file in * ; do echo -n "$file"$'\0' ; done \
| while IFS= read -r -d $'\0' ; do echo "$REPLY" ; done
Run Code Online (Sandbox Code Playgroud)
当我只尝试for-loop 部分时,我发现它只是将所有文件名打印在一起,中间没有空字节。
为什么是这样?这是怎么回事?
我正在使用以下命令清空某些 Linux 4.x 操作系统上的硬盘驱动器:
sudo sh -c 'pv -pterb /dev/zero > /dev/sda'
Run Code Online (Sandbox Code Playgroud)
我打开另一个 tty 并开始sudo htop注意到这一点:
PID USER PRI NI CPU% RES SHR IO_RBYTES IO_WBYTES S TIME+ Command
4598 root 20 0 15.5 1820 1596 4096 17223823 D 1:14.11 pv -pterb /dev/zero
Run Code Online (Sandbox Code Playgroud)
的值IO_WBYTES看起来很正常,但IO_RBYTES保持在 4 KiB 并且永远不会改变。
例如,我运行了一些其他程序
dd if=/dev/zero of=/dev/zero
cat /dev/zero > /dev/zero
Run Code Online (Sandbox Code Playgroud)
并且惊讶地发现它们中没有一个生成大量IO_RBYTESor IO_WBYTES。
我认为这不是特定于任何程序的,但是为什么不读取/dev/zero和写入以/dev/{zero,null}计为 I/O 字节?
如果我这样做:touch file; mv file /dev/null作为根,/dev/null消失。 ls -lad /dev/null结果没有这样的文件或目录。这会破坏依赖于/dev/nullSSH 的应用程序,并且可以通过执行mknod /dev/null c 1 3; chmod 666 /dev/null. 为什么将常规文件移动到这个特殊文件会导致/dev/null?
澄清一下,这是出于测试目的,我了解该mv命令的工作原理。我很好奇的是为什么ls -la /dev/null在用常规文件替换它之前显示预期的输出,但之后它显示/dev/null不存在,即使据称是通过原始mv命令创建的文件并且文件命令显示 ASCII 文本。我认为这必须是ls命令行为与devfs非特殊文件替换字符/特殊文件时的组合。这是在 Mac OS X 上,行为在其他操作系统上可能会有所不同。
我有一个包含超过 400 GiB 数据的目录。我想检查所有文件是否可以正确读取,所以我想到的一个简单方法是将tar其放入/dev/null. 但相反,我看到了以下行为:
$ time tar cf /dev/null .
real 0m4.387s
user 0m3.462s
sys 0m0.185s
$ time tar cf - . > /dev/null
real 0m3.130s
user 0m3.091s
sys 0m0.035s
$ time tar cf - . | cat > /dev/null
^C
real 10m32.985s
user 0m1.942s
sys 0m33.764s
Run Code Online (Sandbox Code Playgroud)
上面的第三个命令在运行了很长时间后被Ctrl+强行停止C。此外,当前两个命令正在工作时,包含的存储设备的活动指示器.几乎总是空闲的。使用第三个命令时,指示灯会持续亮起,表示非常忙碌。
所以看起来,当tar能够发现它的输出文件是 时/dev/null,即当/dev/null直接打开有tar写入的文件句柄时,文件体似乎被跳过了。(添加v选项tar确实将目录中的所有文件打印为tar“红色”。)
所以我想知道,为什么会这样?这是某种优化吗?如果是,那么为什么还要tar对这种特殊情况进行如此可疑的优化?
我在 Linux …
我想在设置中测试一些物理链接。我可以用来测试这个的软件工具需要一个块设备来读/写。我可用的块设备无法使物理链路饱和,因此我无法对其进行全面测试。
我知道我可以设置一个由文件支持的虚拟块设备。所以我的想法是以某种方式将虚拟块设备设置为 /dev/null 但问题当然是我无法从中读取。有没有一种方法可以设置一个写入 /dev/null 但在读取时总是返回零的虚拟块设备?
感谢您的任何帮助!
我知道 Linux 中的文件名没有任何限制,除了两个字符'/'和'\0'. 我知道这'/'是禁止的,因为它是目录分隔符,但还有其他原因吗?
同样在我的终端上,我可以创建一个名为\0. 所以我想知道如何正确编写空字符,因为显然它不应该允许我在文件名中包含空字符
mkdir '\0'
将创建一个名为的目录 \0
还有一个问题,如果我想包含$在我的文件名中,我可以使用反斜杠
mkdir \$myfile 将创建一个名为的目录 $myfile
但是,如果我用单引号和双引号将美元符号括起来,我也可以这样做
mkdir \$myfile相同mkdir '$'myfile相同mkdir "$"myfile相同mkdir '$myfile'相同 相同mkdir "$myfile"
所以我的问题是,单引号和双引号是否可以替代转义反斜杠字符?
除了$, (space) 和反斜杠之外,还有哪些其他字符需要在 bash 中转义?
我正在尝试将 python 生成的输入重定向到 bash 5.0.3 中的 ELF 64 位可执行文件。我正进入(状态:
> ./bf <<< $(python2 -c "print('c'*6+b'\x00'+'c'*6)")
bash: warning: command substitution: ignored null byte in input
Enter password: Password didn't match
input: cccccccccccc
Run Code Online (Sandbox Code Playgroud)
如何在输入中允许空字节?
所以我想将 binaryFile.dd 的前 512 个字节作为第二个参数传递给 myProgram 但 bash 去掉了所有的 NUL 字符。有什么办法可以在 bash 中避免这种情况,还是我什么都没有隐藏?
myProgram parameter1 "$(head -c 512 binaryFile.dd)"
Run Code Online (Sandbox Code Playgroud) null ×10
bash ×4
devices ×3
linux ×2
binary ×1
block-device ×1
executable ×1
filenames ×1
files ×1
io ×1
networking ×1
osx ×1
shell ×1
shell-script ×1
tar ×1