[英]Thread using subprocess.communicate() throws the error: b'standard in must be a tty\\n'
我在使用Python中的Thread中的subprocess.Popen()调用脚本时遇到问题。 我尽可能多地添加了细节。 如果我需要在问题中添加更多详细信息,请告知我们。 任何帮助是极大的赞赏。 提前致谢。
TL:DR subprocess.Popen()期待stdin并抛出错误“tandard in must be tty”,即使调用的脚本不需要任何stdin。 此问题开始出现,因为在调用脚本时使用了“su userName -c”
细节
我正在使用django开发一个Web应用程序,它在后端执行PERL脚本。 我正在以root用户身份部署应用程序,我打算以触发它的用户身份运行脚本。 我将从我们页面中的用户那里获取userName。
初始命令测试:我以root身份登录,并且我使用以下命令以用户身份启动脚本:
su userName -c ' /path_to_my_script/reImage.pm --host abcdefg --version 1.2.3.5000'
以上工作正常,并按照用户在以root用户身份登录的终端中调用时指定的方式运行。 所以我理解上面的命令没有问题。
工作流程:
当用户提供输入并在网页中提交输入时,我启动一个守护程序线程,在后台调用上述命令。 一旦调用该命令,perl脚本就完成其任务并返回结果。
我在views.py中使用以下代码来创建一个线程(注意:我只编写与问题相关的代码行而不是views.py的完整内容)
from threading import Thread
reImageThread = Thread(name = hostName, target = reImageFunction ,args = (hostName,buildNumber,userName) )
reImageThread.daemon = True
reImageThread.start()
reImageFunction在另一个文件中定义如下:
import subprocess
def reImageFunction(hostName,buildNumber,userName):
command = " /path_to_my_script/reImage.pm --host "+str(hostName)+" --version "+str(buildNumber)+" " #Blank space at the end is added intentionally
command = " su " + userName + " -c \' " + command + " \' "
print(command) #printing for debugging
#The final command composed would of the format shown in the begenning of this question.
pipe = subprocess.Popen(command , stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
(result,err) = pipe.communicate()
print(err) #Printing the err for debugging
.... #Processing the result
.... #Processing the result
错误:b'standard in必须是tty \\ n'在pipe.communicate()中被抛出
我已经明确提到stdin将是None。 但我不明白为什么子进程仍然需要一些输入。
观察:
当我删除“su username -c”部分时,上面的命令通过子进程执行而没有任何问题,如下所示。 但这不是预期的功能,所以我必须以触发它的用户身份运行它。
没有“su userName -c”部分的示例命令:
/path_to_my_script/reImage.pm --host abcdefg --version 1.2.3.5000
由于添加了“su userName -c”,因此问题开始出现。
我试过以下:
谢谢你的耐心和阅读,直到最后,
我找到了解决问题的方法。
最初,当我尝试从终端使用以下内容时,
sudo -u userName command
我无法执行,因为我遇到了“权限被拒绝”错误。 所以后来我开始从终端使用以下命令
su userName -c "command"
这个su命令在终端上运行良好。 现在是时候在我的Web应用程序中使用它来通过subprocess.invoke(命令)在系统上调用此命令,这就是我得到“标准必须是tty”错误的地方。
我在评论中跟随了@Ryan给出的链接,并在/ etc / sudoers文件中更改了root用户的requiretty,如下所示,这也无济于事。
Defaults:root !requiretty
最后,当我评论“Defaults:requiretty”时(我知道这可能会引起安全问题,但它对于这个应用程序来说很有用)并且在subprocess.invoke ()中使用了su -userName命令 ,它按预期工作。 现在我能够以请求的用户身份运行脚本。
谢谢阅读,
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.