创建目录时,mkdir -m <mode> <dir>
提供使用给定模式/权限集(原子地)创建一个或多个目录。
是否有在命令行上创建文件的等效方法?
类似于:
open("file", O_WRONLY | O_APPEND | O_CREAT, 0777);
使用touch
后跟是chmod
我在这里唯一的选择吗?
编辑:在尝试了 teppic 的建议后install
,我运行了它,strace
看看它与原子有多接近。答案是,不太:
$ strace install -m 777 /dev/null newfile
...
open("newfile", O_WRONLY|O_CREAT|O_EXCL, 0666) = 4
fstat(4, {st_mode=S_IFREG|0666, st_size=0, ...}) = 0
...
fchmod(4, 0600) = 0
close(4) = 0
...
chmod("newfile", 0777) = 0
...
不过,它只是一个 shell 命令,而且是我以前不知道的。
答案1
答案2
touch
如果文件不存在,则始终创建该文件,始终遵循符号链接,并且始终使文件不可执行。您可以通过以下方式决定读取和写入位掩码。
(umask 077; touch file) # creates a 600 (rw-------) file
(umask 002; touch file) # creates a 664 (rw-rw-r--) file
O_NOFOLLOW
使用传统的 shell 工具不可能创建“安全”的原子文件(特别是使用)。你可以sysopen
在perl中使用。如果您有受 BSD 启发的实用程序,它会使用;mktemp
自动创建一个文件。如果默认模式 600 不正确,O_NOFOLLOW
您必须稍后再调用。chmod
答案3
答案4
我不认为你真的可以通过标准工具来做到这一点,但是如果你可以访问 python 解释器,你可以这样做:
python3 -c 'import os, sys, shutil; shutil.copyfileobj(sys.stdin, open("filename.txt", "w", opener=lambda name, flag: os.open(name, flag, mode=0o631)))' <<< "file_content"
展开后,Python 脚本基本上执行以下操作:
import os, sys, shutil
file_opener = lambda name, flag: os.open(name, flag, mode=0o631)
dest = open("filename.txt", "w", opener=file_opener)
shutil.copyfileobj(sys.stdin, dest)
其他脚本语言解释器的工具包中可能有类似的东西。
输出strace
:
$ strace python3 -c 'import os, sys, shutil; shutil.copyfileobj(sys.stdin, open("filename.txt", "w", opener=lambda name, flag: os.open(name, flag, mode=0o631)))' <<< "file_content"
...
openat(AT_FDCWD, "filename.txt", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0631) = 3
ioctl(3, FIOCLEX) = 0
newfstatat(3, "", {st_mode=S_IFREG|0631, st_size=0, ...}, AT_EMPTY_PATH) = 0
ioctl(3, TCGETS, 0x7ffe4fce65e0) = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR) = 0
ioctl(3, TCGETS, 0x7ffe4fce6430) = -1 ENOTTY (Inappropriate ioctl for device)
lseek(3, 0, SEEK_CUR) = 0
brk(0x55c88d356000) = 0x55c88d356000
read(0, "file_content\n", 65536) = 13
brk(0x55c88d346000) = 0x55c88d346000
read(0, "", 65523) = 0
read(0, "", 65536) = 0
write(3, "file_content\n", 13) = 13
...
或者,如果您关心原子性的唯一原因只是为了防止从以其他用户身份运行的敌对进程中读取文件内容,而不一定是使用原子性本身open(..., mode)
,那么您可以在子进程中将 umask 设置为 777,这样该文件首先创建是为了拒绝所有人的权限:
$ (umask 777; <<< "file_content" > filename.txt)
$ ls -lah filename.txt
---------- 1 lieryan lieryan 13 Sep 8 15:58 filename.txt
然后立即使用正确的值设置文件权限:
$ chmod 631 filename.txt
或者,将它们放在一起:
$ (umask 777; <<< "file_content" > filename.txt; chmod 631 filename.txt)
这仍然容易受到以同一用户身份运行的其他进程的竞争条件攻击,但如果您必须担心这一点,那么您可能担心的是错误的事情。