Когда я подключаюсь по ssh к удаленному серверу и запускаю env
Я возвращаю следующий ПУТЬ:
PATH=/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/myusername/bin
Напротив, когда я выполняю команду ansible ansible -a "env"
, Я получаю следующий ПУТЬ:
PATH=/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin
Как можно догадаться, это вызывает проблемы при попытке запустить sbin
такие команды, как service
, ntpdate
и т. д., поскольку для этого нужно ввести полный путь к команде sbin. (Да, я знаю, что есть доступные модули, которые могут это делать, но я пытаюсь решить, почему PATH укорачивается / усекается.)
Кто-нибудь знает, почему это происходит?
РЕДАКТИРОВАТЬ: Причина, по которой я спрашиваю об этом, заключается в том, что я следую примерам из книги Ansible for DevOps
и некоторые примеры не работают по этой причине.
Пример, который я пытаюсь заставить работать, взят со страницы 28 книги:
$ ansible multi -s -a "service ntpd stop"
$ ansible multi -s -a "ntpdate -q 0.rhel.pool.ntp.org"
$ ansible multi -s -a "service ntpd start"
Эти команды всегда вызывают ошибку. Но если я изменю их, чтобы включить полный путь, они работают.
$ ansible multi -s -a "/sbin/service ntpd stop"
$ ansible multi -s -a "/usr/sbin/ntpdate -q 0.rhel.pool.ntp.org"
$ ansible multi -s -a "/sbin/service ntpd start"
Естественно, я не хочу, чтобы мне приходилось вводить полный путь для каждой специальной команды, которую я выполняю. (Я не знаю пути каждой команды.)
Есть ли способ получить обычный путь, который в моей оболочке включен в ansible? Есть ли переменная пути, которую я могу добавить в файл инвентаризации или файл ansible.cfg, чтобы это произошло?
ansible -a
использует командный модуль и это не использует оболочку для выполнения команды.
http://docs.ansible.com/ansible/intro_adhoc.html
Обычно команды также принимают -m в качестве имени модуля, но имя модуля по умолчанию - «команда».
Компоненты пути, такие как /usr/sbin
добавляются к пути оболочкой, получающей /etc/profile
файл, а командный модуль не создает авторизоваться shell, чтобы он не читал этот файл.
http://linux.die.net/man/1/bash
Когда bash вызывается как интерактивная оболочка входа или как неинтерактивная оболочка с параметром --login, она сначала считывает и выполняет команды из файла / etc / profile, если этот файл существует. После чтения этого файла он ищет ~ / .bash_profile, ~ / .bash_login и ~ / .profile в указанном порядке, а также читает и выполняет команды из первого существующего и доступного для чтения файла. Параметр --noprofile может использоваться при запуске оболочки, чтобы запретить такое поведение.
В доступных документах говорится, что если вам нужна оболочка, используйте оболочка модуль. Однако не похоже, что есть возможность запустить оболочку входа из модуля оболочки (путем передачи параметра --login) в любом случае.
Фактически, в разных местах упоминается, что доступная политика заключается в том, чтобы не доверять среде и явно устанавливать любые VARS при определении задачи.
Однако можно указать путь при использовании ansible в режиме ad-hoc. Это ближайшее, что я мог бы сделать, чтобы воспроизвести ПУТЬ, который вы видите в интерактивном /bin/bash
оболочка;
$ ansible raspberrypi -m shell \
-a 'PATH=$PATH:/usr/local/sbin:/usr/sbin:$HOME/bin env' \
| grep PATH
PATH=/usr/local/bin:/usr/bin:/bin:/usr/games:/usr/local/sbin:
/usr/sbin:/home/pi/bin
или, в качестве альтернативы, вы можете получить /etc/profile
файл;
$ ansible raspberrypi -m shell \
-a 'executable=/bin/bash source /etc/profile ; env | grep PATH'
PATH=/opt/consul/bin:/usr/local/sbin:/usr/local/bin:
/usr/sbin:/usr/bin:/sbin:/bin
похоже, это тоже работает;
$ ansible raspberrypi -a '/bin/bash -l -c "env"'
PATH=/opt/consul/bin:/usr/local/sbin:/usr/local/bin:
/usr/sbin:/usr/bin:/sbin:/bin
Итак, учитывая, что ваш вопрос в конечном итоге касается запуска команд под sudo с помощью ansible, я еще раз посмотрел, как устанавливается PATH при использовании ansible -s -a env
. Я думаю, важно отметить, что при использовании sudo -s
недоступен, $ PATH устанавливается другим механизмом, чем при использовании только ansible -a env
.
Когда используешь sudo command
или ansible -s
среда пользователя сбрасывается, а $ PATH управляется Default secure_path
установка в /etc/sudoers
и это объясняется в человек sudoers документация;
По умолчанию опция env_reset включена. Это вызывает выполнение команд в новой минимальной среде. Новая среда содержит переменные TERM, PATH, HOME, MAIL, SHELL, LOGNAME, USER, USERNAME и SUDO_ * в дополнение к переменным из вызывающего процесса, разрешенным параметрами env_check и env_keep.
Если вы не установите значение для Default secure_path
, то эти значения жестко закодированы в двоичный файл sshd, см. этот ответ для подробностей.
Однако по умолчанию в Fedora / centros / ubuntu значение $ PATH берется из secure_path, установленного в /etc/sudoers
;
secure_path - путь, используемый для каждой команды, запускаемой из sudo.
Например, на моем локальном хосте fedora он имеет следующую строку в /etc/sudoers
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
и если я запустил env
удаленно с помощью ssh и sudo я получаю точный путь обратно;
$ ssh localhost "sudo env" | grep PATH
PATH=/sbin:/bin:/usr/sbin:/usr/bin
и я получаю то же самое, используя ansible;
$ ansible localhost -s -a 'env' | grep PATH
PATH=/sbin:/bin:/usr/sbin:/usr/bin
и я пробовал то же самое на экземпляре raspbian (debian), и у меня такое же поведение;
$ ansible raspberrypi -s -a 'cat /etc/sudoers' | grep secure
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
и это путь, который видит ansible с -s -a
параметры;
$ ansible raspberrypi -s -a env | grep PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Итак, что касается вашего первоначального вопроса, я бы взглянул на /etc/sudoers
файл и проверьте значение Defaults secure_path="/some/path/here"
.
Если у вас нет значения, которое включает соответствующий sbin/
directory, то следующая команда в ansible не будет работать, если не указан полный путь;
ansible multi -s -a "service ntpd stop"
Каждый раз, когда я использовал ansible, он запускался от имени другого пользователя ... под другой оболочкой. должен иметь возможность видеть, что делает пользователь:
ansible -a "id"
затем вы можете увидеть оболочку пользователя, определенную в: cat /etc/passwd
Лучше всего добавить к пути, добавив строку: /home/<username>/.profile
или ~/.bash_profile