Почему POSIX требует определенных встроек Shell, чтобы иметь внешнюю реализацию?

Простой способ сделать это, если он соответствует вашим потребностям, - это иметь специальный файл журнала, который обновляется каждый день. Сначала вы добавляете в / etc / (r) syslog.conf , вероятно, в самом верху на случай, если есть какие-то правила, которые что-то отбрасывают после регистрации:

*.*           -/var/log/daily.log

Он получит все сообщения; то есть все, что есть в любом другом журнале, будет в этом.

Тогда вам просто понадобится скрипт, который можно запустить через cron. Вы можете использовать для этого logrotate , но в этом случае особого смысла нет.

#!/bin/sh

gzip /var/log/daily.log
# Do whatever with the gzipped file
touch /var/log/daily.log
kill -s HUP `pidof syslogd`   # see below

Этот последний шаг необходим для перезапуска syslogd, поэтому он повторно открывает новый /var/log/daily.log - иначе вы ничего не увидите там после этого. Если вы используете rsyslog, используйте вместо него pidof rsyslogd . Протестируйте, попробовав pidof , который когда-либо был первым.

Наконец, в / etc / crontab :

0 0  * * *  root   /path/to/rotationscript

Будет делать это в полночь каждый день.

19
24.01.2019, 00:28
3 ответа

Это правило «как если бы».

Проще говоря :Поведение оболочки, как ее видят пользователи, не должно измениться, если реализация решит сделать стандартную внешнюю команду также доступной как встроенную -оболочку.

Контраст, который я показал в https://unix.stackexchange.com/a/496291/5132, между поведением (, с одной стороны, )оболочек PD Korn, MirBSD Korn и Heirloom Bourne; (с другой стороны )оболочки Z, 93 Korn, Bourne Again и Debian Almquist; и (на хватающей руке )панцирь Ватанабэ подчеркивает это.

Для оболочек, не имеющих printfв качестве встроенного -, удаление /usr/binиз PATHприводит к прекращению работы вызова printf.Поведение, соответствующее POSIX, демонстрируемое оболочкой Watanabe в соответствующем режиме, приводит к тому же результату. Поведение оболочки, в которую встроен printf-, такое , как если бы она вызывала внешнюю команду.

Принимая во внимание, что поведение всех несовместимых -оболочек не меняется, если /usr/binудалить из PATH, и они не ведут себя так, как если бы они вызывали внешнюю команду.

Что стандарт пытается гарантировать вам, так это то, что оболочки могут создавать -во всех видах обычно внешних команд (или реализовывать их как свои собственные функции оболочки ), и вы все равно получите то же самое. поведение встроенных -модулей, как вы делали с внешними командами, если вы настроите PATH, чтобы запретить поиск команд. PATHостается вашим инструментом для выбора и управления тем, какие команды вы можете вызывать.

(Как объясняется в https://unix.stackexchange.com/a/448799/5132, много лет назад люди выбирали индивидуальность своего Unix, изменяя то, что было на PATH.)

Можно подумать, что заставить команду работать всегда независимо от того, можно ли ее найти на PATH, на самом деле является смыслом создания обычно внешних команд, встроенных -в (. ] Вот почему мой набор инструментов nosh только что получил встроенную команду -в printenvв версии 1.38. Хотя это не оболочка.)

Но стандарт дает вам гарантию, что вы увидите такое же поведение для обычных внешних команд, которые не включены PATHиз оболочки, как вы увидите из другой оболочки, отличной от -программы, вызывающие функцию execvpe(), и оболочка волшебным образом не сможет выполнять (видимо )обычные внешние команды, которые другие программы не могут найти с тем же PATH. Все работает само -последовательно с точки зрения пользователя, и PATHявляется инструментом для управления тем, как это работает.

Дополнительная литература

17
27.01.2020, 19:45

Это довольно абсурдно, поэтому ни одна оболочка не реализует его в режиме по умолчанию.

Обоснование стандарта и его иллюстрирующий пример предполагают, что это была неудачная попытка построить обычный построенный -путь, и пусть пользователь переопределит его, поставив перед ним свой собственный двоичный файл в PATH(, например. printf, встроенный -, связанный с /usr/bin/printf, может быть переопределен внешней командой /foo/bin/printf, установивPATH=/foo/bin:$PATH).

Тем не менее, стандарт в конечном итоге требовал не этого, а чего-то совершенно другого (, а также бесполезного и неожиданного ).

Подробнее об этом можно прочитать в этом отчете об ошибке . Цитата из окончательно принятого текста :

Many existing implementations execute a regular built-in without performing a PATH search. This behavior does not match the normative text, and it does not allow script authors to override regular built-in utilities via a specially crafted PATH. In addition, the rationale explains that the intention is to allow authors to override built-ins by modifying PATH, but this is not what the normative text says.

FWIW, я также не думаю, что существует какая-либо оболочка, реализующая пересмотренные требования из принятого текста.

15
27.01.2020, 19:45

Следуйте -вверх по сравнению с -и -по отношению к echoпо сравнению сprintf:

(Нижеbuiltinозначает «специальные встроенные функции», а «обычные встроенные функции» я не считаю встроенными, поскольку они не встроены в оболочку)

Первый комитет по стандартизации POSIX не мог договориться о том, как стандартизировать эхо, поэтому они скомпрометировали, выдав, что если оно было передано флаги(-e,-n,-Eи т. д. )или если какие-либо аргументы содержали escape-последовательности(\n,\c,\tи т. д. ), что поведение должно было определяться реализующей оболочкой а не POSIX. Вместо этого была добавлена ​​команда printfс четко определенным -поведением. (источник :Классические сценарии оболочки, Роббинс и Биб ).

Хотя printfхорошо -определено, некоторые оболочки не имеют printfв качестве встроенная команда (например.mksh). Вместо этого они используют printfиз /usr/bin/. Это означало, что все сценарии, запущенные из этой оболочки, будут печатать одно и то же на данная операционная система (Ubuntu, Fedora и т. д. ), но они не обязательно печатать одно и то же в разных ОС (на самом деле, многие пользователи изменили printfв их /usr/binпо этой причине ).

Альтернативно, оболочки со встроенным printfбудут печатать то же самое. независимо от ОС, но только если используется так, как реализовано для оболочки. Однако, поскольку поведение printfопределяется стандартом POSIX, это не обязательно забота программистов. Однако, если бы PATHбыло переопределено для оболочек, использующих printfиз /usr/bin/, printfне было бы найдено.

Хотя все оболочки имеют встроенную функцию echo, некоторые интерпретируют управляющие последовательности. напрямую (.ash)в то время как другие (большинство )требуют флага -e:поведение определяется не POSIX, а оболочкой.

Одно из главных неудобств echoпо сравнению с printfзаключается в том, что echoпечатает новые строки в конце строки по умолчанию, а printf— нет. printfтребует escape-последовательности \nдля печати новых строк. И наоборот, для предотвращения echoдля печати новой строки требуется управляющая последовательность \c(потенциально, также требуется флаг -e).

printfрекомендуется для максимальной переносимости, так как его поведение определяется POSIX, но я лично считаю, что явная печать новой строки в конце каждой строки довольно раздражает (большинство строк, которые я пишу, требуют новой строки в конце, и я очень редко нужно подавлять echoпечать новых строк ). С другой стороны, echoвсегда доступен, поскольку он является встроенным (нет риска быть не найденным в $PATH )и можно выполнить простую проверку, чтобы определить, нужен ли флаг -eи соответствующий псевдоним echo:

#! /bin/sh -

# Determine if "builtin" command exists.
BUILTIN='builtin'
  
if ! ("${BUILTIN}" echo 123 >/dev/null 2>&1); then
  BUILTIN=''
fi
export BUILTIN

ECHO='echo -e'

if ${BUILTIN} [ "`echo -e test`" = '-e test' ]; then
  ECHO='echo'
fi
export ECHO

# Now use "${ECHO}" where you would normally use "echo"...

Лично я предпочитаю делать это и использовать printf, только если мне нужно специальное форматирование.

ОБНОВЛЕНИЕ:Я должен отдать должное там, где это необходимо. Приведенный выше шелл-код был взят непосредственно из shunit2. Это заслуга Кейт Уорд и команды разработчиков shunit2! (Молодец ;))

3
25.05.2021, 23:21

Теги

Похожие вопросы