コマンドラインで設定された権限でファイルを生成できますか?

コマンドラインで設定された権限でファイルを生成できますか?

ディレクトリを作成するときは、mkdir -m <mode> <dir>指定されたモード/権限セットを使用して1つ以上のディレクトリを(原子的に)作成することをお勧めします。

コマンドラインからファイルを生成するのと同等の方法はありますか?

似ている:

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
...

しかし、これは単にシェルコマンドであり、以前は知らなかったコマンドです。

答え1

install次のダミーファイルでコマンドを使用できます。

install -b -m 755 /dev/null newfile

オプションがすでに存在する場合、-bバックアップが作成されます。newfileこのコマンドを使用して所有者を設定することもできます。

Linux では通常 GNU の一部です。コアツールまたは忙しい箱しかし、4.2BSD派生システムでも使用できます。FreeBSDネットワーク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既存のシェルツールを使用して「安全な」アトミックファイルを作成することは不可能です(特に.Perlsysopenで利用可能です。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)

これは、同じユーザーで実行されている他のプロセスの競合状態にまだ脆弱ですが、それを心配する必要がある場合は、おそらく間違ったことを心配しています。

関連情報