Bash에서 리디렉션된 입력을 사용하여 파일에 쓰는 방법은 무엇이며 이를 방지할 수 있습니까?

Bash에서 리디렉션된 입력을 사용하여 파일에 쓰는 방법은 무엇이며 이를 방지할 수 있습니까?

나는 bash 파일 리디렉션을 꽤 잘 처리하고 있다고 생각합니다. 일반적으로 "고양이의 쓸모없는 사용”하지만 스크립트에서 예상치 못한 동작이 발생했는데 왜 이런 일이 발생하는지 알고 싶습니다.

bash 스크립트에서 다음을 실행합니다.

somecommand < file1 > file2

내 기대는 file1이 안전하고 읽기 전용으로 열리는 것입니다. 실제로 file1을 덮어쓸 수 있다는 것을 알았습니다. 어떻게/왜 이런 일이 발생하며 이에 의지하지 않고 해결할 수 있는 방법이 있습니까 cat?

내가 상상하는 대로 작동한다면(프로세스가 직접 rw 파일 설명자로 끝나는가?) 이런 방식으로 파일을 리디렉션하는 것은 위험한 것으로 간주되어야 하는 것처럼 보이지만 이전에는 이런 동작을 본 적이 없습니다.

내 경우에 몇 가지 세부 정보를 추가하려면 문제의 명령은 다음과 같습니다.표준 운영 절차, 백그라운드에서 일부 GPG 작업을 수행합니다. GPG 비밀번호 프롬프트는 입력에 사용된 파일에 덮어쓰여지는 경우가 있습니다 . 내가 사용하는 전체 명령은 다음과 같습니다.

sops --input-type json --output-type json -d /dev/stdin < ./secrets/file.json > ./secrets/file-decrypted.json

나는 그 이후로 전환했고 cat file1 | sops.. > file2모든 것이 예상대로 작동했습니다. 나는 이것이 "고양이에게 쓸모없는 사용"이라고 말했을 것입니다. 그러나 그것은 더 이상 그렇게 쓸모없어 보이지 않습니다!


처음 메시지가 표시되면 gpg-agent가 실행되고 있지 않은 것 같습니다.

답변1

이는 Linux(및 Cygwin이지만 일반적으로 다른 시스템은 아님)에서 /dev/stdin(실질적으로 ) 구현되는 방식 때문입니다 ./proc/self/fd/0

Linux에서 여는 /dev/stdin것은 를 수행하는 것과는 다릅니다 dup(0). 단지 fd 0에서 열린 파일과 동일한 파일을 다시 여는 것뿐입니다. 공유되지 않습니다파일 설명 열기fd 0 참조(읽기 전용 모드 사용), 완전히 관련 없는 새 값을 얻음파일 설명 열기, 모드는 에 지정된 것과 같습니다 open().

따라서 읽기+쓰기 모드로 sops -d /dev/stdin열리고 fd 0 이 /dev/stdin읽기 ​​전용으로 열리면 읽기+쓰기 모드로 열립니다./some/file/some/file

실제로 cmd /dev/stdin < filecmd file < file. 이것은 /dev/stdin단지 심볼릭 링크일 뿐이라는 것을 알 수 있습니다 file.

/tmp$ namei -l /dev/stdin < file
f: /dev/stdin
drwxr-xr-x root     root     /
drwxr-xr-x root     root     dev
lrwxrwxrwx root     root     stdin -> /proc/self/fd/0
drwxr-xr-x root     root       /
dr-xr-xr-x root     root       proc
lrwxrwxrwx root     root       self -> 73569
dr-xr-xr-x stephane stephane     73569
dr-x------ stephane stephane   fd
lr-x------ stephane stephane   0 -> /tmp/file
drwxr-xr-x root     root         /
drwxrwxrwt root     root         tmp
-rw-r--r-- stephane stephane     file

상황이 더 악화될 수 있습니다. O_TRUNC로 열면 파일이 잘립니다. fd 0이 파이프의 읽기 끝을 가리키고 /dev/stdin쓰기 전용 모드로 열리면 파이프의 다른 쪽 끝을 얻게 됩니다.

그러나 다음을 사용하십시오.

cat file | cmd /dev/stdin

파이프가 모든 사람에게 표시되므로 적용 cmd을 방지합니다 . 쓰기 전용 모드로 열리더라도 다시 돌아갈 수 없으며 파이프의 쓰기 끝에만 도달하며 읽기 끝에 있는 유일한 파일 설명자는 stdin입니다.filecmdfilecmd

다른 운영 체제에서는 이 문제가 발생하지 않습니다. 왜냐하면 /dev/stdin이를 여는 것은 a를 실행하는 것과 같기 dup(0)때문에 동일한 결과를 얻을 수 있기 때문입니다.파일 설명 열기호환되지 않는 모드에서 열면 open()시스템 호출이 실패합니다.


1 기술적으로 @ user414777이 의견에서 지적했듯이 /proc/<pid>/fd/<fd>,마법의 심볼릭 링크예를 들어 일반 심볼릭 링크가 갈 수 없는 위치로 이동할 수 있지만 이를 열면 경로 확인 단계 후에 일반 심볼릭 링크처럼 동작하고 대상 파일만 열면 됩니다.

관련 정보