Очевидно, что у многих пользователей есть доступ к sudo, это вызывает беспокойство.
Вместо того, чтобы изобретать колесо, и потому что корневой .profile
запускается только при выполнении sudo su -
, а также потому, что псевдоним sudo помимо не очень удобного, печатается заранее , Рекомендую более стандартный подход.
В конфигурации / etc / sudoers
есть возможность навсегда сохранить предупреждение по умолчанию, которое каждый пользователь получает при первом использовании.
Мы надеемся, что вы прослушали обычную лекцию от локального системного администратора. Обычно это сводится к следующим трем вещам:
# 1) Уважайте частную жизнь других. # 2) Думайте, прежде чем печатать. # 3) С большой властью приходит большая ответственность. { {1}}
пароль root:
Чтобы он всегда был включен, вы создаете файл в / etc / sudoers.d / privacy
с:
Defaults lecture = always
Если вы хотите попробовать это с текущим пользователем, вы должны сначала выйти из системы.
Сообщение по умолчанию находится в исходном коде sudo, если вы хотите его изменить, вам придется перекомпилировать sudo. Я не рекомендую эту идею; если вы настаиваете, вам нужно скомпилировать пакет из apt-src, а затем закрепить / заморозить его, чтобы он не обновлялся случайным образом, а только вручную.
В дополнение к вашему запросу, я настоятельно рекомендую начать регистрацию того, что делают люди, особенно если у них есть неограниченный доступ sudo
.
Если вы добавите в свой /etc/bash.bashrc
:
readonly PROMPT_COMMAND='history -a >(logger -t "commandlog $USER[$PWD] $SSH_CONNECTION")'
Это будет записывать все пользовательские команды в системный журнал.
Я бы настроил syslog
для пересылки журналов на заблокированный центральный сервер syslog, чтобы в случае взлома или мошеннического системного администратора они не смогли подделать доказательства.
Команды в конвейере выполняются одновременно, в этом весь смысл конвейеров и -механизма межпроцессного взаимодействия.
В:
cmd1 | cmd2
cmd1
и cmd2
запускаются одновременно, cmd2
обрабатывает данные, которые cmd1
записывает по мере поступления.
Если вы хотите, чтобы cmd2
запускался только в случае сбоя cmd1
, вам нужно будет запустить cmd2
после того, как cmd1
завершится и сообщит о своем статусе выхода, поэтому вы не можете использовать канал, вам придется использовать временный файл, содержащий все данные, созданные cmd1
:
cmd1 > file || cmd2 < file; rm -f file
Или сохранить в памяти, как в вашем примере, но это имеет ряд других проблем (, таких как $(...)
удаление всех завершающих символов новой строки, и большинство оболочек не могут справиться с байтами NUL там, не говоря уже о масштабировании вопросы для больших выходов ).
В Linux и с такими оболочками, как zsh
или bash
, которые хранят здесь -документы и здесь -строки во временных файлах, вы можете сделать:
{ cmd1 > /dev/fd/3 || cmd2 <&3 3<&-; } 3<<< ignored
Позволить оболочке заниматься созданием и очисткой временного файла -.
bash версии 5 теперь удаляет права на запись во временный файл после его создания, так что описанное выше не будет работать, вам придется обойти это, сначала восстановив разрешение на запись:
{ chmod u+w /dev/fd/3
cmd1 > /dev/fd/3 || cmd2 <&3 3<&-; } 3<<< ignored
Вручную, POSIXly:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/XXXXXX"
) && [ -n "$tmpfile" ] && (
rm -f -- "$tmpfile" || exit
cmd1 >&3 3>&- 4<&- ||
cmd2 <&4 4<&- 3>&-) 3> "$tmpfile" 4< "$tmpfile"
Некоторые системы имеют не -стандартную mktemp
команду (, хотя и с интерфейсом, который различается между системами ), что немного упрощает создание временного файла(tmpfile=$(mktemp)
должно быть достаточно для большинства реализаций, хотя некоторые не создаст файл, поэтому вам может потребоваться настроитьumask
). [ -n "$tmpfile" ]
не должен быть необходим для совместимых m4
реализаций, но GNU m4
по крайней мере не совместим в том смысле, что он не возвращает не -нулевой статус выхода, когда вызов mkstemp()
терпит неудачу.
Также обратите внимание, что ничто не мешает вам запускать какой-либо код в консоли .Ваш "скрипт" можно точно так же ввести в приглашении интерактивной оболочки (, за исключением части return
, которая предполагает, что код находится в функции ), хотя вы можете упростить его к:
output=$(cmd) || grep foo <<< "$output"
Примечание :Поскольку вопрос помечен тегом bash , я предполагаю, что вы можете использовать функции bash.
Судя по вашему примеру кода, вы хотите сделать следующее::
grep
. Запуск grep
на пустом конвейере ничего вам не стоит, поэтому один из вариантов — все равно запустить его и проверить статус выхода команды, который вы можете получить, используя массив PIPESTATUS
в bash:
$ (echo foo; exit 1) | grep foo
foo
$ echo "${PIPESTATUS[@]}"
1 0
Здесь подоболочка завершилась с 1, grep завершилась с 0.
Таким образом, вы можете сделать что-то вроде:
(command | grep -P "foo"; exit "$((PIPESTATUS[0] ? $? : 0))")
Выражение можно упростить, но суть вы поняли.
Также можно просто подделать вывод:
(command && echo foo) | grep -P foo
Где echo foo
будет выполняться только в случае успешного выполнения команды, что приведет к успеху и команды grep.