Comment appeler un script shell à partir de code python?

211

Comment appeler un script shell à partir de code python?

Umesh K
la source

Réponses:

252

Le module de sous-processus vous aidera.

Exemple manifestement trivial:

>>> import subprocess
>>> subprocess.call(['./test.sh']) # Thanks @Jim Dennis for suggesting the []
0 
>>> 

test.shest un simple script shell et 0sa valeur de retour pour cette exécution.

Manoj Govindan
la source
11
Remarque: il est préférable de passer subprocess.call () une liste plutôt qu'une chaîne (voir la commande à Hugo24 ci-dessous pour l'exemple et les raisons).
Jim Dennis
1
Le lien vers le didacticiel est rompu.
Kshitij Saraogi
6
Cela donne: OSError: [Errno 13] Autorisation refusée. mon script n'a pas besoin de s'exécuter avec sudo. @Manoj Govindan
alper
6
Avec des arguments: subprocess.call (['./ test.sh', 'param1', 'param2'])
Henry
2
@alper aller dans le dossier où vous avez placé le script et exécutez la commande, chmod +x script.sh. Remarque: script.sh est un espace réservé pour votre script, remplacez-le en conséquence.
Tom J Muthirenthi
106

Il existe certaines façons d'utiliser os.popen()(obsolète) ou l'ensemble du subprocessmodule, mais cette approche

import os
os.system(command)

est l'un des plus faciles.

Michał Niklas
la source
1
pourquoi n'est-ce pas la réponse la plus votée? N'est-il pas nécessaire d'importer un module, la meilleure solution? Doit être un inconvénient ici?
boulder_ruby
6
Avec, subprocessvous pouvez gérer les canaux d'entrée / sortie / erreur. C'est aussi mieux lorsque vous avez de nombreux arguments - avec os.command()vous devrez créer une ligne de commande entière avec des caractères spéciaux d'échappement, avec une subprocesssimple liste d'arguments. Mais pour des tâches simples, cela os.command() peut suffire.
Michał Niklas
1
Pour citer ce lien:The subprocess module provides more powerful facilities for spawning new processes and retrieving their results; *using that module is preferable to using this function.*
Maximilian
42

Dans le cas où vous souhaitez passer certains paramètres à votre script shell, vous pouvez utiliser la méthode shlex.split () :

import subprocess
import shlex
subprocess.call(shlex.split('./test.sh param1 param2'))

avec test.shdans le même dossier:

#!/bin/sh
echo $1
echo $2
exit 0

Les sorties:

$ python test.py 
param1
param2
Franck Dernoncourt
la source
C'est élégant.
caleb
20
import os
import sys

En supposant que test.sh est le script shell que vous souhaitez exécuter

os.system("sh test.sh")
Srayan Guhathakurta
la source
15

Utilisez le module de sous-processus comme mentionné ci-dessus.

Je l'utilise comme ceci:

subprocess.call(["notepad"])
hugo24
la source
13
Remarque: appeler un sous-processus avec une liste est plus sûr car il ne nécessite pas de passer la chaîne (potentiellement non désinfectée) à travers un shell pour l'analyse / l'interprétation. Le premier élément de la liste sera l'exécutable et tous les autres éléments seront passés en arguments.
Jim Dennis
13

J'utilise python 3.5 et subprocess.call (['./ test.sh']) ne fonctionne pas pour moi.

Je vous donne trois solutions dépend de ce que vous voulez faire avec la sortie.

1 - script d'appel. Vous verrez la sortie dans votre terminal. la sortie est un nombre.

import subprocess 
output = subprocess.call(['test.sh'])

2 - exécution et vidage de l'appel et erreur dans la chaîne. Vous ne voyez pas l'exécution dans votre terminal à moins que vous n'imprimiez (stdout). Shell = True car l'argument dans Popen ne fonctionne pas pour moi.

import subprocess
from subprocess import Popen, PIPE

session = subprocess.Popen(['test.sh'], stdout=PIPE, stderr=PIPE)
stdout, stderr = session.communicate()

if stderr:
    raise Exception("Error "+str(stderr))

3 - appeler le script et vider les commandes d'écho de temp.txt dans temp_file

import subprocess
temp_file = open("temp.txt",'w')
subprocess.call([executable], stdout=temp_file)
with open("temp.txt",'r') as file:
    output = file.read()
print(output)

N'oubliez pas de jeter un œil au sous-processus doc

lauralacarra
la source
1
Remarque N'utilisez pas stdout = PIPE ou stderr = PIPE with subprocess.call. Le processus enfant se bloquera s'il génère suffisamment de sortie vers un tuyau pour remplir le tampon de tuyau du système d'exploitation car les tuyaux ne sont pas lus.
4

Le module de sous-processus est un bon module pour lancer des sous-processus. Vous pouvez l'utiliser pour appeler des commandes shell comme ceci:

subprocess.call(["ls","-l"]);
#basic syntax
#subprocess.call(args, *)

Vous pouvez voir sa documentation ici.

Si votre script est écrit dans un fichier .sh ou une longue chaîne, vous pouvez utiliser le module os.system. C'est assez simple et facile à appeler:

import os
os.system("your command here")
# or
os.system('sh file.sh')

Cette commande exécutera le script une fois, jusqu'à la fin, et bloquera jusqu'à ce qu'il se termine.

Ankit Singh
la source
N'avez-vous pas besoin d'importer des sys aussi?
ScottyBlades
Non, tu ne le fais pas; essayez d'ouvrir un shell Python et d'exécuter cet extrait
Descartes
4

Dans le cas où le script contient plusieurs arguments

#!/usr/bin/python

import subprocess
output = subprocess.call(["./test.sh","xyz","1234"])
print output

La sortie donnera le code d'état. Si le script s'exécute correctement, il donnera 0 sinon un entier différent de zéro.

podname=xyz  serial=1234
0

Voici le script shell test.sh.

#!/bin/bash

podname=$1
serial=$2
echo "podname=$podname  serial=$serial"
Rishi Bansal
la source
2

Le sous-processus est bon mais certaines personnes préfèrent le scriptine . Scriptine a un ensemble de méthodes de plus haut niveau comme shell.call (args) , path.rename (nouveau_nom) et path.move (src, dst) . Le script est basé sur un sous-processus - et d'autres.

Deux inconvénients de la scriptine:

  • Le niveau de documentation actuel serait plus complet même s'il est suffisant.
  • Contrairement au sous-processus, le package scriptine n'est actuellement pas installé par défaut.
Akseli Palén
la source
2

Je sais que c'est une vieille question mais je suis tombé dessus récemment et cela a fini par me tromper depuis le sous- processus API de sous- changé depuis python 3.5.

La nouvelle façon d'exécuter des scripts externes est avec la runfonction, qui exécute la commande décrite par args. Attend la fin de la commande, puis retourne une instance de CompletedProcess.

import subprocess

subprocess.run(['./test.sh'])
Kévin Sanchez Lacroix
la source
1

Si votre fichier de script shell n'a pas d'autorisations d'exécution, procédez comme suit.

import subprocess
subprocess.run(['/bin/bash', './test.sh'])
thomasXu
la source
-9

Veuillez essayer les codes suivants:

Import Execute 

Execute("zbx_control.sh")
Manas
la source