可以使用命令行上设置的权限创建文件吗?

可以使用命令行上设置的权限创建文件吗?

创建目录时,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

您可以将install命令与虚拟文件一起使用,例如

install -b -m 755 /dev/null newfile

如果该选项已存在,则会-b进行备份。newfile您也可以使用此命令来设置所有者。

在 Linux 上它通常是 GNU 的一部分核心工具或者忙碌盒,但它也可以在 4.2BSD 派生的系统上使用,例如自由BSD,网络BSD或者开放BSD

答案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

以@teppic 为基础回答,如果您想同时创建包含内容和模式的文件(bash):

install -m 755 <(echo commands go here) newscript

<()将输出放入临时文件中,请参阅流程替代

答案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)

这仍然容易受到以同一用户身份运行的其他进程的竞争条件攻击,但如果您必须担心这一点,那么您可能担心的是错误的事情。

相关内容