从python脚本以超级用户身份运行命令

时间:2021-02-11 02:41:52

So I'm trying to get a process to be run as a super user from within a python script using subprocess. In the ipython shell something like

因此,我正在尝试使用子进程从python脚本中以超级用户身份运行进程。在ipython shell中就像是

proc = subprocess.Popen('sudo apach2ctl restart',
                        shell=True, stdin=subprocess.PIPE,
                        stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE)

works fine, but as soon as I stick it into a script I start getting: sudo: apach2ctl: command not found.

工作正常,但一旦我把它插入脚本我开始得到:sudo:apach2ctl:命令未找到。

I would guess this is due to the way sudo handles environments on ubuntu. (I've also tried sudo -E apche2ctl restart and sudo env path=$PATH apache2ctl restart with no avail)

我猜这是由于sudo在ubuntu上处理环境的方式。 (我也试过sudo -E apche2ctl restart和sudo env path = $ PATH apache2ctl restart无效)

So my question is basically, if I want to run apache2ctl restart as super user that prompts the user for the super user password when required, how should I go about doing this? I have no intention of storing passwords in the script.

所以我的问题基本上是,如果我想以超级用户身份运行apache2ctl restart,在需要时提示用户输入超级用户密码,我应该怎么做呢?我无意在脚本中存储密码。

Edit:

编辑:

I've tried passing in the commands as both a string and tokenized into a list. In the python interpreter, with a string I'll get the password prompt properly (still doesnt work in a python script as in my original problem), a list just gives the help screen for sudo.

我已经尝试将命令作为字符串传递并标记为列表。在python解释器中,使用字符串我将正确地获得密码提示(仍然不像我原来的问题那样在python脚本中工作),列表只给出了sudo的帮助屏幕。

Edit 2:

编辑2:

So what I gather is that while Popen will work with some commands just as strings when shell=True, it takes

所以我收集到的是,当shell = True时,Popen将使用一些命令作为字符串,这需要

proc = subprocess.Popen(['sudo','/usr/sbin/apache2ctl','restart'])

without 'shell=True' to get sudo to work.

没有'shell = True'让sudo工作。

Thanks!

谢谢!

6 个解决方案

#1


15  

Try giving the full path to apache2ctl.

尝试给出apache2ctl的完整路径。

#2


22  

Try:

尝试:

subprocess.call(['sudo', 'apach2ctl', 'restart'])

subprocess.call(['sudo','apach2ctl','restart'])

The subprocess needs to access the real stdin/out/err for it to be able to prompt you, and read in your password. If you set them up as pipes, you need to feed the password into that pipe yourself.

子进程需要访问真正的stdin / out / err才能提示您,并读入您的密码。如果将它们设置为管道,则需要自己将密码提供给该管道。

If you don't define them, then it grabs sys.stdout, etc...

如果你没有定义它们,那么它会抓取sys.stdout等...

#3


9  

Another way is to make your user a password-less sudo user.

另一种方法是让您的用户成为无密码的sudo用户。

Type the following on command line:

在命令行上键入以下内容:

sudo visudo

Then add the following and replace the <username> with yours:

然后添加以下内容并将 替换为您的:

<username> ALL=(ALL) NOPASSWD: ALL

This will allow the user to execute sudo command without having to ask for password (including application launched by the said user. This might be a security risk though

这将允许用户执行sudo命令而无需询问密码(包括由所述用户启动的应用程序。这可能存在安全风险

#4


3  

You have to use Popen like this:

你必须像这样使用Popen:

cmd = ['sudo', 'apache2ctl', 'restart']
proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

It expects a list.

它需要一份清单。

#5


3  

I used this for python 3.5. I did it using subprocess module.Using the password like this is very insecure.

我用这个用于python 3.5。我使用子进程模块做到了。使用这样的密码是非常不安全的。

The subprocess module takes command as a list of strings so either create a list beforehand using split() or pass the whole list later. Read the documentation for more information.

子进程模块将命令作为字符串列表,因此要么事先使用split()创建列表,要么稍后传递整个列表。阅读文档以获取更多信息。

What we are doing here is echoing the password and then using pipe we pass it on to the sudo through '-S' argument.

我们在这里做的是回显密码,然后使用管道,我们通过'-S'参数将其传递给sudo。

#!/usr/bin/env python
import subprocess

sudo_password = 'mysecretpass'
command = 'apach2ctl restart'
command = command.split()

cmd1 = subprocess.Popen(['echo',sudo_password], stdout=subprocess.PIPE)
cmd2 = subprocess.Popen(['sudo','-S'] + command, stdin=cmd1.stdout, stdout=subprocess.PIPE)

output = cmd2.stdout.read().decode() 

#6


2  

I tried all the solutions, but did not work. Wanted to run long running tasks with Celery but for these I needed to run sudo chown command with subprocess.call().

我尝试了所有解决方案,但没有奏效。想要使用Celery运行长时间运行的任务,但是对于这些我需要使用subprocess.call()运行sudo chown命令。

This is what worked for me:

这对我有用:

To add safe environment variables, in command line, type:

要添加安全环境变量,请在命令行中键入:

export MY_SUDO_PASS="user_password_here"

To test if it's working type:

要测试它是否正在工作:

echo $MY_SUDO_PASS
 > user_password_here

To run it at system startup add it to the end of this file:

要在系统启动时运行它,请将其添加到此文件的末尾:

nano ~/.bashrc  

#.bashrc
...
existing_content:

  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi
...

export MY_SUDO_PASS="user_password_here"

You can add all your environment variables passwords, usernames, host, etc here later.

您可以稍后在此处添加所有环境变量密码,用户名,主机等。

If your variables are ready you can run:

如果您的变量准备就绪,您可以运行:

To update:

更新:

echo $MY_SUDO_PASS | sudo -S apt-get update

Or to install Midnight Commander

或者安装午夜指挥官

echo $MY_SUDO_PASS | sudo -S apt-get install mc

To start Midnight Commander with sudo

用sudo开始午夜指挥官

echo $MY_SUDO_PASS | sudo -S mc

Or from python shell (or Django/Celery), to change directory ownership recursively:

或者从python shell(或Django / Celery),以递归方式更改目录所有权:

python
>> import subprocess
>> subprocess.call('echo $MY_SUDO_PASS | sudo -S chown -R username_here /home/username_here/folder_to_change_ownership_recursivley', shell=True)

Hope it helps.

希望能帮助到你。

#1


15  

Try giving the full path to apache2ctl.

尝试给出apache2ctl的完整路径。

#2


22  

Try:

尝试:

subprocess.call(['sudo', 'apach2ctl', 'restart'])

subprocess.call(['sudo','apach2ctl','restart'])

The subprocess needs to access the real stdin/out/err for it to be able to prompt you, and read in your password. If you set them up as pipes, you need to feed the password into that pipe yourself.

子进程需要访问真正的stdin / out / err才能提示您,并读入您的密码。如果将它们设置为管道,则需要自己将密码提供给该管道。

If you don't define them, then it grabs sys.stdout, etc...

如果你没有定义它们,那么它会抓取sys.stdout等...

#3


9  

Another way is to make your user a password-less sudo user.

另一种方法是让您的用户成为无密码的sudo用户。

Type the following on command line:

在命令行上键入以下内容:

sudo visudo

Then add the following and replace the <username> with yours:

然后添加以下内容并将 替换为您的:

<username> ALL=(ALL) NOPASSWD: ALL

This will allow the user to execute sudo command without having to ask for password (including application launched by the said user. This might be a security risk though

这将允许用户执行sudo命令而无需询问密码(包括由所述用户启动的应用程序。这可能存在安全风险

#4


3  

You have to use Popen like this:

你必须像这样使用Popen:

cmd = ['sudo', 'apache2ctl', 'restart']
proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

It expects a list.

它需要一份清单。

#5


3  

I used this for python 3.5. I did it using subprocess module.Using the password like this is very insecure.

我用这个用于python 3.5。我使用子进程模块做到了。使用这样的密码是非常不安全的。

The subprocess module takes command as a list of strings so either create a list beforehand using split() or pass the whole list later. Read the documentation for more information.

子进程模块将命令作为字符串列表,因此要么事先使用split()创建列表,要么稍后传递整个列表。阅读文档以获取更多信息。

What we are doing here is echoing the password and then using pipe we pass it on to the sudo through '-S' argument.

我们在这里做的是回显密码,然后使用管道,我们通过'-S'参数将其传递给sudo。

#!/usr/bin/env python
import subprocess

sudo_password = 'mysecretpass'
command = 'apach2ctl restart'
command = command.split()

cmd1 = subprocess.Popen(['echo',sudo_password], stdout=subprocess.PIPE)
cmd2 = subprocess.Popen(['sudo','-S'] + command, stdin=cmd1.stdout, stdout=subprocess.PIPE)

output = cmd2.stdout.read().decode() 

#6


2  

I tried all the solutions, but did not work. Wanted to run long running tasks with Celery but for these I needed to run sudo chown command with subprocess.call().

我尝试了所有解决方案,但没有奏效。想要使用Celery运行长时间运行的任务,但是对于这些我需要使用subprocess.call()运行sudo chown命令。

This is what worked for me:

这对我有用:

To add safe environment variables, in command line, type:

要添加安全环境变量,请在命令行中键入:

export MY_SUDO_PASS="user_password_here"

To test if it's working type:

要测试它是否正在工作:

echo $MY_SUDO_PASS
 > user_password_here

To run it at system startup add it to the end of this file:

要在系统启动时运行它,请将其添加到此文件的末尾:

nano ~/.bashrc  

#.bashrc
...
existing_content:

  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi
...

export MY_SUDO_PASS="user_password_here"

You can add all your environment variables passwords, usernames, host, etc here later.

您可以稍后在此处添加所有环境变量密码,用户名,主机等。

If your variables are ready you can run:

如果您的变量准备就绪,您可以运行:

To update:

更新:

echo $MY_SUDO_PASS | sudo -S apt-get update

Or to install Midnight Commander

或者安装午夜指挥官

echo $MY_SUDO_PASS | sudo -S apt-get install mc

To start Midnight Commander with sudo

用sudo开始午夜指挥官

echo $MY_SUDO_PASS | sudo -S mc

Or from python shell (or Django/Celery), to change directory ownership recursively:

或者从python shell(或Django / Celery),以递归方式更改目录所有权:

python
>> import subprocess
>> subprocess.call('echo $MY_SUDO_PASS | sudo -S chown -R username_here /home/username_here/folder_to_change_ownership_recursivley', shell=True)

Hope it helps.

希望能帮助到你。