Как трусить STDOUT команды, в зависимости от результата кода выхода

Очевидно, что у многих пользователей есть доступ к 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, чтобы в случае взлома или мошеннического системного администратора они не смогли подделать доказательства.

6
25.10.2018, 22:18
2 ответа

Команды в конвейере выполняются одновременно, в этом весь смысл конвейеров и -механизма межпроцессного взаимодействия.

В:

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"
18
27.01.2020, 20:20

Примечание :Поскольку вопрос помечен тегом , я предполагаю, что вы можете использовать функции bash.

Судя по вашему примеру кода, вы хотите сделать следующее::

  • Использовать статус выхода команды, если он равен 0,
  • В противном случае используйте статус выхода 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.

5
27.01.2020, 20:20

Теги

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