我尝试过以下方法:
invoke_shell()
然后发送su
和密码结果没有获得 root 权限invoke_shell()
然后使用channel.exec_command
结果出现了 "Channel Closed" 错误_transport.open_session()
然后使用channel.exec_command
结果没有获得 root 权限invoke_shell()
然后写入 stdin 并刷新,结果没有获得 root 权限
我尝试过以下方法:
invoke_shell()
然后发送 su
和密码结果没有获得 root 权限invoke_shell()
然后使用 channel.exec_command
结果出现了 "Channel Closed" 错误_transport.open_session()
然后使用 channel.exec_command
结果没有获得 root 权限invoke_shell()
然后写入 stdin 并刷新,结果没有获得 root 权限来看这个例子:
ssh.connect('127.0.0.1', username='jesse',
password='lol')
stdin, stdout, stderr = ssh.exec_command(
"sudo dmesg")
stdin.write('lol\n')
stdin.flush()
data = stdout.read.splitlines()
for line in data:
if line.split(':')[0] == 'AirPort':
print line
在这里找到更多解释的示例: http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/
希望对你有所帮助!
stdin、stdout、stderr = ssh.exec_command("sudo -S %s" % command)
# 如果stdout仍然打开,则sudo正在请求我们输入密码
if stdout.channel.closed is False:
stdin.write('%s\n' % password)
stdin.flush()
- Haroldo_OKget_pty=True
,所以你需要使用:ssh.exec_command('你的命令', get_pty=True)
。 - sliders_alphainvoke_shell
对我来说是这样工作的:
import paramiko, getpass, re, time
ssh_client = paramiko.SSHClient()
ssh_client.connect( host )
sudo_pw = getpass.getpass("sudo pw for %s: " % host)
command = "sudo magicwand"
channel = ssh_client.invoke_shell()
channel.send( command )
# wait for prompt
while not re.search(".*\[sudo\].*",channel.recv(1024)): time.sleep(1)
channel.send( "%s\n" % sudo_pw )
while not loop
真的很有用!谢谢分享! :) - Paul Calabro\r
。否则什么也不会发生。 - Adrian WAlexS
进行了微调之后的答案(现在我正在生产中使用)如下:
def sudo_run_commands_remote(command, server_address, server_username, server_pass, server_key_file):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=server_address,
username=server_username,
password=server_pass,
key_filename=server_key_file)
session = ssh.get_transport().open_session()
session.set_combine_stderr(True)
session.get_pty()
session.exec_command("sudo bash -c \"" + command + "\"")
stdin = session.makefile('wb', -1)
stdout = session.makefile('rb', -1)
stdin.write(server_pass + '\n')
stdin.flush()
print(stdout.read().decode("utf-8"))
如果您不使用密钥文件,可以从 connect
方法中删除 key_filename
部分;反之,如果您只使用没有密码的密钥,请删除 password
部分。
需要注意的是,这是多命令能力。这意味着它作为 root
运行了一个 bash
,因此您可以在单个运行中尽可能多地运行命令,只需用 ;
分隔即可。
您可以使用通道发送sudo密码:
passwd = getpass.getpass()
ssh = paramiko.client.SSHClient()
ssh.set_missing_host_key_policy(paramiko.client.AutoAddPolicy())
ssh.load_system_host_keys()
ssh.connect(host, allow_agent=True)
chan = ssh.get_transport().open_session()
chan.get_pty()
chan.setblocking(1)
chan.exec_command("sudo -k dmesg")
while chan.recv_ready()==False:
stdout=chan.recv(4096)
if re.search('[Pp]assword', stdout):
chan.send(passwd+'\n')
time.sleep(1)
while chan.recv_ready():
stdout += chan.recv(20000)
chan.close()
ssh.close()
很抱歉我没有时间提供详细的解释,但是我成功地使用这个建议在paramiko上实现了sudo命令。
import paramiko
l_password = "yourpassword"
l_host = "yourhost"
l_user = "yourusername"
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(l_host, username=l_user, password=l_password)
transport = ssh.get_transport()
session = transport.open_session()
session.set_combine_stderr(True)
session.get_pty()
#for testing purposes we want to force sudo to always to ask for password. because of that we use "-k" key
session.exec_command("sudo -k dmesg")
stdin = session.makefile('wb', -1)
stdout = session.makefile('rb', -1)
#you have to check if you really need to send password here
stdin.write(l_password +'\n')
stdin.flush()
for line in stdout.read().splitlines():
print 'host: %s: %s' % (l_host, line)
myuser ALL=NOPASSWD:/home/myuser/somescript.sh
su
|sudo
)并编辑sudoers文件或运行脚本进行编辑。如果您只能通过paramiko
访问远程系统,则可能很难或不可能实现。例如,您正在自动化某些操作,您不想为每个主机手动准备脚本。 - Jury我想到了这个:
def ssh_command(ssh_client, command, sudo=False):
"""Like SSHClient.exec_command, but raises if the command fails.
Otherwise, the stdout result is returned as a string.
"""
nbytes = 4 * 2e20 # 4 MiB
with ssh_client.get_transport().open_session() as channel:
command = 'sudo ' + command if sudo else command
if sudo:
channel.set_combine_stderr(True)
channel.get_pty()
channel.exec_command(command)
if sudo:
while not channel.recv_ready():
stdout = channel.recv(nbytes).decode('UTF-8')
if re.search('[Pp]assword', stdout):
channel.send(ROBOT_PASSWORD + '\n')
time.sleep(1)
status = channel.recv_exit_status() # blocking call
if status != 0:
if sudo:
output = channel.recv(nbytes).decode('UTF-8')
else:
output = channel.recv_stderr(nbytes).decode('UTF-8')
raise RuntimeError(f'command {command} exited with {status}, '
f'output: {output}')
return channel.recv(nbytes).decode('UTF-8')
我很惊讶这种基本功能被留给Paramiko用户自己重新发明。
我能够在远程服务器上手动运行sudo cupsdisable
命令,而无需在以管理员用户(非root)登录到该服务器时输入密码,但是当我使用stdin、stdout和stderr = client.exec_command("sudo cupsdisable <Printqueuename>")
执行相同的命令时,它什么也不做。
对我有效的命令是:
stdin, stdout, stderr = client.exec_command("sudo -u root /usr/sbin/cupsdisable <printQueuename>")
这仅适用于上述情况。希望能对某些人有所帮助。