私はLinuxシェルコマンドを実行し、コマンドの詳細をSQLデータベースに書き込むいくつかのアプリケーションコードを書いています。これには、STDOUT + STDERR(別途)の出力が含まれます。
コマンドの実行後にプロセスが何も出力しないと仮定すると、STDOUT / STDERRフィールドをNULLにして空の文字列に設定する理由はありますか?
つまり、これら2つの間に技術的な違いはありますか?
- 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
組み込みの場合はシェルを実行します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