Executando o script bash de dentro do python


105

Tenho um problema com o seguinte código:

callBash.py:

import subprocess
print "start"
subprocess.call("sleep.sh")
print "end"

sleep.sh:

sleep 10

Quero que o "final" seja impresso após 10s. (Eu sei que este é um exemplo idiota, eu poderia simplesmente dormir dentro do python, mas este arquivo sleep.sh simples foi apenas como um teste)


Também tentei com "$! Bin / bash; sleep 10;"
user1638145

Não está claro qual é o problema que esse questionador está tentando fazer, mas a pergunta provavelmente deve permanecer, porque acumulou uma coleção histórica de suposições mais ou menos boas como respostas. Provavelmente também pesquise seu erro específico e / ou leia perguntas relacionadas, como stackoverflow.com/questions/4256107/…
tripleee

Respostas:


91

Tornar o sleep.sh executável e adicionar shell=Trueà lista de parâmetros (como sugerido nas respostas anteriores) funciona bem. Dependendo do caminho de pesquisa, você também pode precisar adicionar ./ou algum outro caminho apropriado. (Ou seja, mude "sleep.sh"para "./sleep.sh".)

O shell=Trueparâmetro não é necessário (em um sistema Posix como o Linux) se a primeira linha do script bash for um caminho para um shell; por exemplo #!/bin/bash,.


48

Se sleep.shtiver o shebang #!/bin/she as permissões de arquivo apropriadas - execute chmod u+rx sleep.shpara certificar-se de que está dentro, $PATHentão seu código deve funcionar como está:

import subprocess

rc = subprocess.call("sleep.sh")

Se o script não estiver no PATH, especifique o caminho completo para ele, por exemplo, se estiver no diretório de trabalho atual:

from subprocess import call

rc = call("./sleep.sh")

Se o script não tiver nenhum shebang, você precisará especificar shell=True:

rc = call("./sleep.sh", shell=True)

Se o script não tiver permissões executáveis ​​e você não puder alterá-lo, por exemplo, executando os.chmod('sleep.sh', 0o755), você pode ler o script como um arquivo de texto e passar a string para o subprocessmódulo:

with open('sleep.sh', 'rb') as file:
    script = file.read()
rc = call(script, shell=True)

34

Na verdade, você só precisa adicionar o shell=Trueargumento:

subprocess.call("sleep.sh", shell=True)

Mas cuidado -

Aviso Chamar o shell do sistema com shell = True pode ser um risco à segurança se combinado com uma entrada não confiável. Consulte o aviso em Argumentos usados ​​com frequência para obter detalhes.

fonte


1
Não funcionará se sleep.shnão estiver no PATH. E se estiver no caminho e tiver o conteúdo correto, você não precisa shell=True. Veja minha resposta
jfs

16

Se alguém procura chamar um script com argumentos

import subprocess

val = subprocess.check_call("./script.sh '%s'" % arg, shell=True)

Lembre-se de converter os args em string antes de passar, usando str (arg).

Isso pode ser usado para passar quantos argumentos desejar:

subprocess.check_call("./script.ksh %s %s %s" % (arg1, str(arg2), arg3), shell=True)

10

Certifique-se de que sleep.shtem permissões de execução e execute-o com shell=True:

#!/usr/bin/python

import subprocess
print "start"
subprocess.call("./sleep.sh", shell=True)
print "end"

então foi o shell = True que perdi. Você poderia explicar por que não é suficiente definir #! Bin / bash na primeira linha do sh scricpt?
user1638145

3
O erro #!bin/bashestá ausente /. #!/bin/bashfunciona como eu observo em uma resposta.
James Waldby - jwpat7

9

Se o chmod não funcionar, você também tenta

import os
os.system('sh script.sh')
#you can also use bash instead of sh

teste por mim obrigado


A os.systemdocumentação recomenda especificamente evitá-lo em favor de subprocess(atualmente, subprocess.run()). Se você não consegue subprocesstrabalhar, é provável que tenha problemas os.system()também.
tripleee

3

Adicionando uma resposta porque fui direcionado aqui depois de perguntar como executar um script bash em python. Você receberá um erro OSError: [Errno 2] file not foundse o seu script aceitar parâmetros. Digamos, por exemplo, que seu script tenha um parâmetro de tempo de suspensão: subprocess.call("sleep.sh 10")não funcionará, você deve passá-lo como uma matriz:subprocess.call(["sleep.sh", 10])


Você tem que entender o significado real de,shell=True mas sim, geralmente evitá-lo é sua melhor jogada.
tripleee
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.