简体   繁体   English

在具有 sudo 权限的远程服务器上运行 python 脚本

[英]Running a python script on a remote server with sudo privileges

I got to know about python pexcept package to solve my problem of running python script on remote server as root, using the following code:我了解了 python pexcept 包来解决我在远程服务器上以 root 身份运行 python 脚本的问题,使用以下代码:

import pexpect

# Set the username for ssh connection
username = 'zod1@<remote-server-ip>'

# Take a valid password from the user
Password = input("Enter the login password of %s: " %username)

# Run ssh command using spawn
child = pexpect.spawn('ssh ' + username)

# Wait for the password
child.expect('password:')

# Send the password taken from the user
child.sendline(Password)

# Expected three output
i = child.expect (['Permission denied', 'Terminal type', '[#\$] '])

# i will be 0 if ssh is unable to connect
if i == 0:
    print("Permission denied by host. Unable to login")
    child.kill(0)

# i will be 1 if ssh is able to connect but terminal is not set
elif i == 1:
    print('Connected Successfully.\nTerminal type is not set.')
    child.sendline('vt100')
    child.expect('[#\$]')

# i will be 2 if ssh is able to connect and terminal is set
elif i == 2:
    print('Connected Successfully.')
    prompt = child.after
    print('Shell Command Prompt:', prompt.decode("utf-8"))

till here everything works fine, but I need to execute the next parts of the script(not included here) as root user, for that i'm using:到这里一切正常,但我需要以 root 用户身份执行脚本的下一部分(此处不包括),因为我正在使用:

pwd = input("super user password: ")
child = pexpect.spawn('sudo su')
i = child.expect(['[sudo] password for zod1:']) 
child.sendline(pwd)

which gives:这使:

Traceback (most recent call last):
  File "/Users/ravi3.intern/Desktop/new.py", line 131, in <module>
    i = child.expect(['[sudo] password for zod1:']) 
  File "/opt/homebrew/lib/python3.9/site-packages/pexpect/spawnbase.py", line 343, in expect
    return self.expect_list(compiled_pattern_list,
  File "/opt/homebrew/lib/python3.9/site-packages/pexpect/spawnbase.py", line 372, in expect_list
    return exp.expect_loop(timeout)
  File "/opt/homebrew/lib/python3.9/site-packages/pexpect/expect.py", line 181, in expect_loop
    return self.timeout(e)
  File "/opt/homebrew/lib/python3.9/site-packages/pexpect/expect.py", line 144, in timeout
    raise exc
pexpect.exceptions.TIMEOUT: Timeout exceeded.
<pexpect.pty_spawn.spawn object at 0x100c36f40>
command: /usr/bin/sudo
args: ['/usr/bin/sudo', 'su']
buffer (last 100 chars): b'Password:'
before (last 100 chars): b'Password:'
after: <class 'pexpect.exceptions.TIMEOUT'>
match: None
match_index: None
exitstatus: None
flag_eof: False
pid: 94531
child_fd: 6
closed: False
timeout: 30
delimiter: <class 'pexpect.exceptions.EOF'>
logfile: None
logfile_read: None
logfile_send: None
maxread: 1
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1
searcher: searcher_re:
    0: re.compile(b'[sudo] password for zod1:'

which seems to getting stuck on child.expect part.这似乎卡在 child.expect 部分。 I tested the same thing with 'date' instead of 'sudo su' which seems to be working fine with the above approach.我用 'date' 而不是 'sudo su' 测试了同样的东西,这似乎与上述方法工作得很好。 So, can someone please help in debugging the error.. TIA!那么,有人可以帮助调试错误.. TIA!

Your search term in expect doesn't match the output from pexpect.before , which is before (last 100 chars): b'Password:' .您在expect中的搜索词与pexpect.before的输出不匹配,即before (last 100 chars): b'Password:' You'll want to change that line to:您需要将该行更改为:

i=child.expect('Password:')

As another suggestion to improve your code, you can also search on the timeout so that you handle that exception yourself.作为改进代码的另一个建议,您还可以搜索超时,以便您自己处理该异常。 For example:例如:

i=child.expect(['Password:',pexpect.TIMEOUT], timeout=5)
if i==0:
    child.sendline(Password)
elif i==1:
    print('Command failed to run, timeout')

The problems in the above script were:上述脚本中的问题是:

  1. i = child.expect(['[sudo] password for zod1:'])

    Here, [sudo] was not escaped like \[sudo\] hence, pexpect was not able to find match since it expects a pattern.在这里, [sudo]没有像\[sudo\]那样转义,因此 pexpect 无法找到匹配项,因为它需要一个模式。

  2. child = pexpect.spawn('sudo su') spawned a new independent process instead of continuing with the already spawned process. child = pexpect.spawn('sudo su')生成了一个新的独立进程,而不是继续已经生成的进程。 Using child.sendline('sudo su') resolved the issue.使用child.sendline('sudo su')解决了这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM