Как выполнить несколько команд в одной сессии с помощью Paramiko? (Python)
Описание проблемы
Я столкнулся с проблемой при использовании библиотеки Paramiko для выполнения команд на удалённом сервере. У меня есть следующий код для выполнения команд с помощью метода exec_command
:
def exec_command(self, command, bufsize=-1):
# print "Executing Command: " + command
chan = self._transport.open_session()
chan.exec_command(command)
stdin = chan.makefile('wb', bufsize)
stdout = chan.makefile('rb', bufsize)
stderr = chan.makefile_stderr('rb', bufsize)
return stdin, stdout, stderr
Проблема заключается в том, что каждый раз при выполнении команды с помощью exec_command
сессия сбрасывается. Это означает, что если я запущу команду, требующую привилегий, например sudo
или su
, они не сохраняются при выполнении следующего вызова exec_command
.
Кроме того, если я попытаюсь выполнить команду exec_command("cd /")
, то при следующем вызове exec_command
текущее рабочее направление будет сброшено, и выполнение произойдёт в исходной директории сессии, а не в корне. Я понимаю, что можно объединить команды, используя синтаксис exec_command("cd /; ls -l")
, но мне нужно выполнять команды в отдельных вызовах функции.
Вопрос: Как я могу сохранить состояние сессии между этими вызовами, чтобы выполнять команды с повышенными привилегиями или оставаться в нужной директории без объединения команд?
5 ответ(ов)
Попробуйте создать строку команды, разделённую символом \n
. У меня это сработало. Например: ssh.exec_command("command_1 \n command_2 \n command_3")
.
Строго говоря, вы не можете. Согласно спецификации SSH:
Сессия — это удаленное выполнение программы. Программа может быть оболочкой, приложением, системной командой или встроенным подсистемой.
Это означает, что после завершения выполнения команды сессия считается завершенной. Вы не можете выполнить несколько команд в одной сессии. Однако вы можете запустить удаленную оболочку (то есть одну команду) и взаимодействовать с этой оболочкой через стандартный ввод и другие каналы (подумайте о выполнении скрипта на Python по сравнению с запуском интерактивного интерпретатора).
Чтобы выполнить команды на удалённом сервере с использованием SSH в Python, вы можете использовать библиотеку paramiko
. В приведённом примере кода сначала выполняется команда для просмотра содержимого каталога, а затем для чтения файла журнала. Вот перевод кода на русский язык в формате ответа на StackOverflow:
cmd = 'ls /home/dir' # Команда для получения списка файлов в каталоге /home/dir
self.ssh_stdin, self.ssh_stdout, self.ssh_stderr = self.ssh.exec_command(cmd) # Выполнение команды
print(self.ssh_stdout.read()) # Вывод результата выполнения команды
cmd2 = 'cat /home/dir/test.log' # Команда для чтения содержимого файла test.log
self.ssh_stdin2, self.ssh_stdout2, self.ssh_stderr2 = self.ssh.exec_command(cmd2) # Выполнение второй команды
print(self.ssh_stdout2.read()) # Вывод содержимого файла
Если вам нужно объяснить, как это работает, то можно добавить:
exec_command
выполняет указанную команду на удаленном сервере через SSH.- Результаты команды сохраняются в отдельных переменных
ssh_stdin
,ssh_stdout
иssh_stderr
.ssh_stdout
содержит стандартный вывод команды.ssh_stderr
будет содержать ошибки, если они возникают.
- Метод
read()
позволяет вам считать весь вывод, который был получен при выполнении команды.
Если есть дополнительные вопросы или необходимо больше деталей, не стесняйтесь спрашивать!
Вы можете выполнить несколько команд, используя следующий метод. Используйте точку с запятой для разделения команд в Linux. Например:
chan.exec_command("date;ls;free -m")
Таким образом, каждая команда будет выполнена последовательно.
Если вы хотите, чтобы каждое последующее командное действие зависело от успешного выполнения предыдущего, вы можете использовать следующий синтаксис:
stdin, stdout, stderr = client.exec_command("command1;command2;command3")
Однако в некоторых случаях я заметил, что использование ";"
может не сработать, но &&
работает так, как вы ожидаете:
stdin, stdout, stderr = client.exec_command("command1 && command2 && command3")
В этом случае &&
гарантирует, что следующая команда будет выполняться только в том случае, если предыдущая команда завершилась успешно (т.е. с кодом возврата 0).
Как изменить порядок столбцов в DataFrame?
'pip' не распознан как командa внутреннего или внешнего формата
Почему statistics.mean() работает так медленно?
Преобразование строки даты JSON в datetime в Python
Есть ли разница между поднятием экземпляра класса Exception и самого класса Exception?