저는 Linux 셸 명령을 실행한 다음 명령 세부 정보를 SQL 데이터베이스에 기록하는 일부 애플리케이션 코드를 작성 중입니다. 여기에는 STDOUT + STDERR(별도)의 출력이 포함됩니다.
명령을 실행한 후 프로세스가 아무것도 출력하지 않는다고 가정하면... STDOUT/STDERR 필드를 NULL로 남겨두고 빈 문자열로 설정하는 이유가 있습니까?
즉, 이 두 가지 사이에 기술적 차이가 있습니까?
- STDOUT에 아무것도 출력하지 않는 프로세스
- STDOUT에 빈 문자열(그 이상은 없음)을 출력하는 프로세스
다시 다른 방법으로 질문해 보겠습니다. SQL에서 이러한 열을 NOT NULL로 만드는 것이 합리적입니까?
답변1
파이프(std-err/out)에는 빈 문자열이라는 개념이 없으며 단지 "출력 없음"일 뿐입니다.
> printf ''
> printf '' | xxd
null은 무엇입니까?
> printf '\0'
> printf '\0' | xxd
00000000: 00
데이터베이스에서는 그 반대가 사실이고, 적을수록 많으므로 스크립트를 자동으로 만들고(빈 문자열) 데이터베이스를 빈(비어 있음)로 설정하십시오.
답변2
질문을 이해했는지 잘 모르겠지만:
표준 출력에 쓰기가 실행 중입니다.
write(1, memory_address, length)
메모리 주소에 저장된 길이 바이트를 파일 설명자 1(stdout의 경우 1, stderr의 경우 2)에 씁니다. 예를 들어, in echo test
, echo
(또는 echo
내장된 경우 shell) 을 실행합니다 write(1, "test\n", 5)
.
그러나 이것은 약간 어리석은 일입니다. write()
길이가 0인 시스템 호출을 호출할 수 있습니다.
그리고:
write(1, address, 0)
적어도 Linux에서는 시스템 호출이 파일 설명자가 쓰기 또는 읽기+쓰기 모드로 열렸는지, 주소가 유효한 주소인지(읽을 수 있을 필요는 없지만) 확인합니다. stdout이 손상된 파이프인 경우 SIGPIPE 신호가 전달되지 않을 것이라고 생각합니다.
따라서 크기 0을 수행하는 것은 쓰기를 전혀 수행하지 않는 것과 엄격하게 동일하지 않습니다. 오류가 발생할 수 있기 때문입니다.
실제로 대부분의 명령은 " write()
if can"을 사용하지 않는 것으로 나타났습니다.
나는 이것을 발견했고 echo -n
내가 시도한 어떤 구현에서도 printf ''
시스템 호출을 하지 않습니다 . write()
stdio 함수( fputs()
// ... printf()
빈 문자열을 쓰도록 요청하면 fwrite()
아무 작업도 수행하지 않습니다 .)write()
0 길이 쓰기를 수행하려면 다음을 시도해 보십시오.
perl -e 'syswrite(STDOUT, "")'
또는
python -c 'import os; os.write(1, "")'
이러한 인터프리터의 원래 인터페이스는 write()
.
예:
$ strace -e write /bin/echo -n
$ strace -e write python -c 'import os; os.write(1, "")'
write(1, "", 0) = 0
$ python -c 'import os; os.write(1, "")' >&-
Traceback (most recent call last):
File "<string>", line 1, in <module>
OSError: [Errno 9] Bad file descriptor
$ python -c 'import os; os.write(1, "")' 1< /dev/null
Traceback (most recent call last):
File "<string>", line 1, in <module>
OSError: [Errno 9] Bad file descriptor
$ printf '%s\n' '#include <unistd.h>' 'main(){write(1,(char*)-1,0);}' | strace -e write tcc -run -
write(1, "", 0) = -1 EFAULT (Bad address)
$ printf '%s\n' '#include <unistd.h>' 'main(){write(1,(char*)0,1);}' | strace -e write tcc -run -
write(1, NULL, 1) = -1 EFAULT (Bad address)
$ printf '%s\n' '#include <unistd.h>' 'main(){write(1,(char*)0,0);}' | strace -e write tcc -run -
write(1, NULL, 0) = 0