在具有Sudo特权的远程服务器上运行Python脚本

发布于 2025-02-04 14:00:16 字数 2789 浏览 10 评论 0原文

我了解了Python Pexcept软件包,以解决我在远程服务器上运行Python脚本作为root的问题,使用以下代码:

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"))

直到这里一切正常,但是我需要执行脚本的下一个部分(此处不包括此处) root用户,为此,我使用的是:

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

给出的:

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:'

这似乎被卡在child.sprect part上。我用“日期”而不是“ sudo su”测试了同一件事,这似乎在上述方法方面正常工作。因此,有人可以帮助调试错误。

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:

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:

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. I tested the same thing with 'date' instead of 'sudo su' which seems to be working fine with the above approach. So, can someone please help in debugging the error.. TIA!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

反话 2025-02-11 14:00:16

您的搜索词期望pexpect.before的输出不匹配,该输出是之前的(最后100个字符):b'Password:'。您需要将该行更改为:

i=child.expect('Password:')

作为改进代码的另一个建议,您还可以在超时搜索,以便自己处理该异常。例如:

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

Your search term in expect doesn't match the output from pexpect.before, which is 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')
囚你心 2025-02-11 14:00:16

以上脚本中的问题是:

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

    在这里
    找到匹配项,因为它会带来模式。

  2. child = pexpect.spawn('sudo su')产生了一个新的独立过程
    而不是继续存在的过程。使用
    child.sendline('sudo su')解决了问题。

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.

  2. child = pexpect.spawn('sudo su') spawned a new independent process
    instead of continuing with the already spawned process. Using
    child.sendline('sudo su') resolved the issue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文