英文:
Python2.7 - Execute shell command with subprocess and use output for the other
问题
我尝试在一个Pod中执行一些命令,但它没有生效。你有什么建议?
import subprocess
p = subprocess.Popen('kubectl get pods -o=custom-columns=NAME:.metadata.name | grep -i nottepod', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
print line,
# 这里的line = Pod的确切名称。在这之后不起作用。它不能登录到Pod中。
p2 = subprocess.Popen("kubectl exec -it" + $(line) + "-- bash", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
p3 = subprocess.Popen("ls -lrth", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line2 in p3.stdout.readlines():
print line2,
retval = p3.wait()
我期望在p2步骤中进入Pod后运行一些命令。
我真正尝试的是首先获取Pod的名称(p1),然后使用exec命令登录到Pod中(p2),这就是我需要p1输出的原因。在登录到Pod后,我还需要运行一些命令(p3等),这是我的主要目的。在下面,你可以看到当我手动运行它们时发生了什么。
[abc@master ~]$ kubectl get pods -o=custom-columns=NAME:.metadata.name | grep -i nottepod
nottepod-xyz
[abc@master ~]$ kubectl exec -it nottepod-xyz -- bash
Defaulted container "notte" out of: notte, key
[root@master -notte ]# ls -lrth
total 216M
drwxr-xr-x 2 root root 6 Jul 6 2022 Cache
-rwxr-xr-x 3 1037 users 111 Dec 26 16:51 start.sh
-rwxr-xr-x 3 1037 users 291 Dec 26 16:51 rataten.sh
英文:
I'm trying to execute some command in a pod but it's not working. What could be your suggessing?
import subprocess
p = subprocess.Popen('kubectl get pods -o=custom-columns=NAME:.metadata.name | grep -i nottepod' , shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
print line,
#Here the line = exact name of the pod. After here not working. it's not login to the pods
p2 = subprocess.Popen("kubectl exec -it' +$(line)+ '-- bash'" , shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
p3 = subprocess.Popen("ls -lrth" , shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line2 in p3.stdout.readlines():
print line2,
retval = p3.wait()
I expect to run a couple of command after get in the pod with p2 step.
What I really try is, first, get the pods name(p1), login to the pod with exec command(p2) that's why I need p1 output to use in it. After I'm login to the pod, I also need to run some commands (p3..etc) That's my main purpose. Below you can see what's happening when I run them manually.
> [abc@master ~]$ kubectl get pods -o=custom-columns=NAME:.metadata.name | grep -i nottepod
>
> nottepod-xyz
>
> [abc@master ~]$
>
> [abc@master ~]$ kubectl exec -it nottepod-xyz -- bash
>
> Defaulted container "notte" out of: notte, key
>
> [root@master -notte ]# ls -lrth
>
> [root@master -notte ]# ls -lrth
>
> total 216M
>
> drwxr-xr-x 2 root root 6 Jul 6 2022 Cache
>
> -rwxr-xr-x 3 1037 users 111 Dec 26 16:51 start.sh
>
> -rwxr-xr-x 3 1037 users 291 Dec 26 16:51 rataten.sh
答案1
得分: 2
If you merely meant to interpolate the Python variable named line
, you probably want
p2 = subprocess.check_output(
["kubectl", "exec", "-it", line, "--",
"bash", "-c", "couple of commands; more commands"])
Notice how this also avoids the overhead and security implications of shell=True
Generally, avoid Popen
always when you can.
If you really want the exec bash
to accept commands interactively, you do need Popen
, and need to submit those commands as standard input to the interactive shell. But this is probably best avoided if you can.
Here is a refactoring to use check_output
throughout, and avoid shell=True
everywhere.
import subprocess
pods = subprocess.check_output(['kubectl', 'get', 'pods', '-o=custom-columns=NAME:.metadata.name'])
nottepod = [pod for pod in pods.splitlines() if 'nottepod' in pod.lower()]
assert len(nottepod) == 1
nottepod = pod[0]
print(nottepod,)
lsout = subprocess.check_output(
['kubectl', 'exec', '-it', nottepod, '--',
'bash', '-c', 'ls -lrth'])
for line in lsout.splitlines():
print(line,)
Splitting the output into lines only then to print them each separately is obviously silly, but I imagine you might want to do something more useful with each output line ultimately. If not, simply print(lsout,)
in one go for simplicity.
英文:
If you merely meant to interpolate the Python variable named line
, you probably want
p2 = subprocess.check_output(
["kubectl", "exec", "-it", line, "--",
"bash", "-c", "couple of commands; more commands"])
Notice how this also avoids the overhead and security implications of shell=True
Generally, avoid Popen
always when you can.
If you really want the exec bash
to accept commands interactively, you do need Popen
, and need to submit those commands as standard input to the interactive shell. But this is probably best avoided if you can.
Here is a refactoring to use check_output
throughout, and avoid shell=True
everywhere.
import subprocess
pods = subprocess.check_output(['kubectl', 'get', 'pods', '-o=custom-columns=NAME:.metadata.name'])
nottepod = [pod for pod in pods.splitlines() if 'nottepod' in pod.lower()]
assert len(nottepod) == 1
nottepod = pod[0]
print(nottepod,)
lsout = subprocess.check_output(
['kubectl', 'exec', '-it', nottepod, '--',
'bash', '-c', 'ls -lrth'])
for line in lsout.splitlines():
print(line,)
Splitting the output into lines only then to print them each separately is obviously silly, but I imagine you might want to do something more useful with each output line ultimately. If not, simply print(lsout,)
in one go for simplicity.
(The following was part of my original answer before you clarified your question. I have moved it down here in case there are future visitors with a different problem.)
The expression $(line)
is wrong, but we can't really guess what you hope for it to mean.
If line
is a command you want to run as a command substitution, the syntax is correct as such, but you will probably want to remove the single quotes and the plus marks around it, and maybe add double quotes. (This seems implausible, but I'll mention it anyway.)
# XXX FIXME: implausible but still possible
p2 = subprocess.check_output(
'kubectl exec -it "$(line)" -- bash',
shell=True)
If you wanted to use the value of the Python variable line
as the command to run, that's
# XXX FIXME: also implausible but still possible
p2 = subprocess.check_output(
'kubectl exec -it "$(' + shlex.quote(line) + ')" -- bash',
shell=True)
It's not clear what you wanted to do with the output from the subprocess. You might want to use check_call
if you don't care about the output, but then you probably want stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
if you don't want them displayed to the user.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论