STDOUT + STDERR вывод … есть ли разница между тем, чтобы считать вывод пустой строкой и NULL.

Вопрос или проблема

Я пишу некоторый код приложения, который используется для выполнения команд оболочки Linux, а затем логирует детали команд в SQL базе данных. Это включает вывод STDOUT + STDERR (отдельно).

После выполнения команды и если процесс ничего не вывел… может ли быть какая-либо причина оставить поля STDOUT/STDERR равными NULL, а не задать их как пустые строки?

Чтобы переформулировать вопрос: есть ли технически какая-либо разница между этими двумя случаями?

  • Процесс, который ничего не выводит в STDOUT
  • Процесс, который выводит пустую строку в STDOUT (и ничего больше)

И снова переформулируя вопрос… имеет ли смысл сделать эти столбцы NOT NULL в SQL?

В канале (std-err/out) нет концепции пустой строки, это просто “нет вывода”;

> printf '' 
> printf '' | xxd

в то время как null – это нечто

> printf '\0'
> printf '\0' | xxd
00000000: 00

Противоположное верно в базе данных, и чем меньше, тем лучше, поэтому пусть ваши скрипты будут молчаливыми (пустая строка), а ваша БД – пустой (null).

Не уверен, что понимаю вопрос, но:

Запись в stdout выполняет:

write(1, memory_address, length)

Что записывает length байтов, сохраненных по адресе memory_address, в дескриптор файла 1 (1 для stdout, 2 для stderr). Например, в echo test, echo (или оболочка, если echo встроен) выполняет write(1, "test\n", 5).

Хотя это немного нелепо, вы можете вызвать системный вызов write() с длиной 0.

При этом:

write(1, address, 0)

По крайней мере на GNU/Linux, системный вызов все равно проверяет, что дескриптор файла был открыт в режиме записи или чтения+записи и что адрес является допустимым адресом (хотя он не обязательно должен быть читабельным). Если stdout является разорванной трубой, я не вижу, чтобы это вызвало получение сигнала SIGPIPE.

Таким образом, выполнение write() нулевого размера не является строго эквивалентным тому, чтобы вообще ничего не писать, поскольку это может вызвать ошибки.

На практике, я замечаю, что большинство команд избегают write(), если могут.

Я обнаружил, что echo -n (стиль Unix V7) или echo '\c' (стиль SysIII) и printf '' не делают никаких вызовов write() во всех реализациях, которые я пробовал. Функции stdio (fputs()/printf()/fwrite()… не выполняют никаких write(), когда вы просите их записать пустую строку).

Чтобы выполнить запись нулевой длины, вы можете попробовать:

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

Ответ или решение

Вопрос, касающийся различий между пустой строкой и значением NULL в контексте вывода стандартного вывода (STDOUT) и стандартного вывода ошибок (STDERR), действительно важен, особенно при разработке приложений, которые взаимодействуют с командной строкой и сохраняют данные в базы данных.

Технические различия между пустой строкой и NULL

  1. Определения:

    • Пустая строка: Это строка, которая существует и имеет длину 0. Она представляется как "" в большинстве языков программирования.
    • NULL: Это специальное значение, указывающее на отсутствие данных. Оно не является строкой и обычно обозначает, что переменная либо не была инициализирована, либо не содержит значимой информации.
  2. Работа с выводом:

    • Если процесс не генерирует вывод (т.е. ничего не пишет в STDOUT или STDERR), этот момент эквивалентен концепции отсутствия вывода. В системном вызове write() процесс может не выполнять никаких действий, что в конечном итоге приводит к тому, что вывод вообще не происходит.
    • В отличие от этого, если процесс явно пишет пустую строку в STDOUT, то выполняется системный вызов write(1, "", 0), который может приводит к выполнению минимальных проверок, но фактически не создает никакого вывода.

SQL и база данных

В контексте вашей базы данных, выбор между использованием NULL и пустой строкой зависит от того, как вы хотите интерпретировать эти значения:

  • NULL:

    • Подразумевает отсутствие данных.
    • Это может быть полезно, когда нужно различить "вывод отсутствует" и "вывод есть, но он пуст".
  • Пустая строка:

    • Указывает на то, что данные существуют, но в данный момент являются пустыми.
    • Подходит, если вы хотите отразить, что процесс выполнился, но вывод не содержал полезной информации.

Решение для столбцов базы данных

Решение о том, делать ли столбцы для STDOUT и STDERR NOT NULL, зависит от потребностей вашей системы:

  1. Если ваша система должна различать отсутствие вывода и пустой вывод, разумно использовать NULL для обозначения отсутствия результатов.
  2. Если же отсутствие информации не имеет значения, и вы хотите упростить логику обработки, вы можете установить пустую строку как значение по умолчанию.

Заключение

Что касается вашего приложения, рекомендуется использовать NULL для обозначения того, что вывод не был сгенерирован, и пустые строки для случаев, когда вывод был, но не имел содержимого. Это позволит избежать путаницы и делать четкое различие между "ничего нет" и "вывод есть, но он пуст".

Таким образом, решение, нужно ли использовать NOT NULL в вашей базе данных, должно основываться на том, какую информацию вы хотите сохранить и как будете обрабатывать эти данные в вашем приложении.

Оцените материал
Добавить комментарий

Капча загружается...