简体   繁体   English

如何使用许多参数执行python subprocess.Popen?

[英]How to execute python subprocess.Popen with many Arguments?

I need to execute the same command on a local and remote server. 我需要在本地和远程服务器上执行相同的命令。 So I'm using subprocess.Popen to execute, and local command work as expected, but when I execute on remote it gives me some error like command not found. 所以我正在使用subprocess.Popen执行,并且本地命令按预期工作,但是当我在远程执行时,它给了我一些错误,例如找不到命令。 I appreciate your support as I am new to this. 感谢您的支持,因为我是新来的。

Local execution function 本地执行功能

    def topic_Offset_lz(self):
         CMD = "/dsapps/admin/edp/scripts/edp-admin.sh kafka-topic offset %s -e %s | grep -v Getting |grep -v Verifying | egrep -v '^[[:space:]]*$|^#' | awk -F\: '{print $3}'|sed '%sq;d'" % (self.topic,self.envr,self.partition)
         t_out_lz, t_error_lz = subprocess.Popen(CMD, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()
         return t_out_lz

Remote server execution 远程服务器执行

    def topic_offset_sl(self):
         CMD = "/dsapps/admin/edp/scripts/edp-admin.sh kafka-topic offset %s -e %s | grep -v Getting |grep -v Verifying | egrep -v '^[[:space:]]*$|^#' | awk -F\: '{print $3}'|sed '%sq;d'" % (self.topic, self.envr, self.partition)
         t_out_sl, t_error_sl = subprocess.Popen(["ssh", "-q", CMD], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()
         return t_error_sl

Error I'm getting for the remote execution 错误我正在执行远程执行

Landing Zone Offset: 0 着陆区偏移量:0

SoftLayer Zone Offset: /bin/sh: ^# |sed 1: command not found /bin/sh: d: command not found SoftLayer区域偏移:/ bin / sh:^#| sed 1:找不到命令/ bin / sh:d:找不到命令

The ssh command passes its argument vector as a single command line string, not an array. ssh命令将其参数向量作为单个命令行字符串而不是数组传递。 To do this, it simply concatenates the arguments, without performing shell quoting: 为此,它仅连接参数,而无需执行shell引用:

$ ssh target "python -c 'import sys;print(sys.argv)'" 1 2 3
['-c', '1', '2', '3']
$ ssh target "python -c 'import sys;print(sys.argv)'" "1 2 3"
['-c', '1', '2', '3']

If there was proper shell quoting, the distinction between 1 2 3 and "1 2 3" would have been preserved, and the first argument would not need double-quoting. 如果有适当的外壳引号,则将保留1 2 3"1 2 3"之间的区别,并且第一个参数不需要双引号。

Anyway, in your case, the following might work: 无论如何,就您而言,以下方法可能会起作用:

def topic_offset_sl(self):
     CMD = "ssh -q " + pipes.quote("/dsapps/admin/edp/scripts/edp-admin.sh"
             + " kafka-topic offset %s -e %s" % (self.topic, self.envr)) \
         + "grep -v Getting |grep -v Verifying | egrep -v '^[[:space:]]*$|^#'"
         + " | awk -F\: '{print $3}'|sed '%sq;d'" % self.partition
     t_out_sl, t_error_sl = subprocess.Popen(CMD], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()
     return t_error_sl

This assumes you only want to run the /dsapps/admin/edp/scripts/edp-admin.sh script remotely and not the rest. 假设您只想远程运行/dsapps/admin/edp/scripts/edp-admin.sh脚本,而不要其余部分。

Note that the way you use string splicing to construct command lines likely introduces shell command injection vulnerabilities (both locally and on the remote server). 请注意,使用字符串拼接来构造命令行的方式可能会引入shell命令注入漏洞(在本地和在远程服务器上)。

I came up with below solution, might be there will easy way rather than this. 我想出了以下解决方案,可能会有简单的方法,而不是这种方法。

 def topic_offset_sl(self):
        CMD_SL1 = "ssh -q %s '/dsapps/admin/edp/scripts/edp-admin.sh kafka-topic offset %s -e %s'" % (KEY_SERVER,self.topic, self.envr)
        CMD_SL2 = "| grep -v Getting |grep -v Verifying | egrep -v '^[[:space:]]*$|^#' | awk -F\: '{print $3}'|sed '%sq;d'" % (self.partition)
        t_out_sl, t_error_sl = subprocess.Popen(CMD_SL1 + CMD_SL2 , stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()
        return t_out_sl

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

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