Debian 10 через SSH игнорирует `DEBIAN_FRONTEND=noninteractive`

Debian 10 через SSH игнорирует `DEBIAN_FRONTEND=noninteractive`

Я пишу несколько скриптов для установки некоторых вещей на сервер под управлением Debian 10.

Вот сценарий:

#!/usr/bin/env sh

address=$1

ssh -T $address <<EOF > /dev/null
  DEBIAN_FRONTEND=noninteractive
  sudo apt-get install --assume-yes docker.io
EOF

Когда я запускаю скрипт, передавая в качестве параметра "[email protected]«Я получаю следующий вывод:

debconf: unable to initialize frontend: Dialog
debconf: (Dialog frontend will not work on a dumb terminal, an emacs shell buffer, or without a controlling terminal.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (This frontend requires a controlling tty.)
debconf: falling back to frontend: Teletype
dpkg-preconfigure: unable to re-open stdin: 

Я так понимаю, что это DEBIAN_FRONTEND=noninteractiveсделано для того, чтобы эти предупреждения не появлялись. Я что-то не понимаю?

Я также пробовал помещать команды в скрипт и запускать скрипт вместо команд. Затем я пробовал не использовать здесь документы, но все равно безуспешно.

решение1

Вот что происходит:

  1. На удаленной стороне SSH-сервер порождает оболочку. Оболочка обрабатывает ваш here-документ, переданный с локальной стороны.
  2. DEBIAN_FRONTEND=noninteractiveопределяет переменную в оболочке. Переменная не экспортируется в среду. Она будет переменной среды, только если она уже является переменной среды; скорее всего, это не так.
  3. Оболочка порождает (или выполняет) sudo. Наследуются только переменные окружения, поэтому sudoне знает ваш DEBIAN_FRONTEND.
  4. sudoпорождает apt-get. Даже если бы инструмент знал DEBIAN_FRONTEND, это нормально для sudoдезинфекции среды его потомка, так что он все равно apt-getне узнает DEBIAN_FRONTEND.

Чтобы справиться с этим, вам нужно экспортировать переменную. Вместо этого DEBIAN_FRONTEND=noninteractiveвам нужно отправить

export DEBIAN_FRONTEND=noninteractive

к удаленной оболочке. Затем вам нужно убедиться, sudoчто не будет скрывать ее от apt-get. См. этот вопрос:Как сохранить переменные окружения при использовании sudo?Из одного из ответов:

вам нужно man sudoвнимательно прочитать и обратить внимание на -Eфлаг. […]

Вот цитата из страницы руководства:

-E, --preserve-env
Указывает политике безопасности, что пользователь хочет сохранить существующие переменные среды. Политика безопасности может вернуть ошибку, если у пользователя нет разрешения на сохранение среды.

В вашем случае документ будет выглядеть так:

export DEBIAN_FRONTEND=noninteractive
sudo -E apt-get install --assume-yes docker.io

В другом ответе упоминается способ указания переменных, которые должны сохраняться без -E: env_keepв sudoersфайле. Я не буду вдаваться в подробности.

Еще один метод: sudoпозволяет вам определять переменные, помещая их между sudoи фактической командой, хотя они также подлежат ограничениям, налагаемым политикой безопасности. Следующий фрагмент должен работать (если политика это допускает) даже без экспорта переменной:

DEBIAN_FRONTEND=noninteractive
sudo DEBIAN_FRONTEND="$DEBIAN_FRONTEND" apt-get install --assume-yes docker.io

Обратите внимание, что с here-document вам нужно <<'EOF'вместо , <<EOFчтобы предотвратить расширение переменной на локальной стороне (или вам нужно экранировать $). Это становится сложным, и хорошая новость в том, что вам вообще не нужна переменная в удаленной оболочке. В вашем случае этого должно быть достаточно, чтобы определить правильную переменную для apt-get:

sudo DEBIAN_FRONTEND=noninteractive apt-get install --assume-yes docker.io

Наконец, в случае, если политика безопасности не позволяет вам указать эту переменную, вы можете создать sudoеще одну оболочку:

sudo sh -c 'DEBIAN_FRONTEND=noninteractive apt-get install --assume-yes docker.io'

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

Связанный контент