Chạy tập lệnh bash từ bên trong python


104

Tôi gặp sự cố với mã sau:

callBash.py:

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

sleep.sh:

sleep 10

Tôi muốn "kết thúc" được in sau 10s. (Tôi biết rằng đây là một ví dụ ngu ngốc, tôi chỉ có thể ngủ trong python, nhưng tệp sleep.sh đơn giản này chỉ là một thử nghiệm)


Tôi cũng đã thử nó với "$! Bin / bash; sleep 10;"
user1638145

Không rõ người hỏi này đang cố hỏi vấn đề gì, nhưng câu hỏi có lẽ nên vẫn giữ nguyên vì nó đã tích lũy một túi lịch sử ít nhiều phỏng đoán tốt làm câu trả lời. Có thể cũng tìm kiếm lỗi cụ thể của bạn và / hoặc đọc các câu hỏi liên quan như stackoverflow.com/questions/4256107/…
tripleee

Câu trả lời:


90

Làm cho sleep.sh có thể thực thi và thêm shell=Truevào danh sách tham số (như được đề xuất trong các câu trả lời trước) hoạt động tốt. Tùy thuộc vào đường dẫn tìm kiếm, bạn cũng có thể cần thêm ./hoặc một số đường dẫn thích hợp khác. (Tức là đổi "sleep.sh"thành"./sleep.sh" .)

Các shell=Truetham số là không cần thiết (dưới một hệ thống Posix như Linux) nếu dòng đầu tiên của kịch bản bash là một đường dẫn đến một vỏ; ví dụ #!/bin/bash,.


47

Nếu sleep.shcó shebang #!/bin/shvà nó có quyền truy cập tệp thích hợp - hãy chạy chmod u+rx sleep.shđể đảm bảo và nó ở trong $PATHthì mã của bạn sẽ hoạt động như sau:

import subprocess

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

Nếu tập lệnh không có trong PATH thì hãy chỉ định đường dẫn đầy đủ đến nó, ví dụ: nếu nó nằm trong thư mục làm việc hiện tại:

from subprocess import call

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

Nếu script không có shebang thì bạn cần chỉ định shell=True:

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

Nếu tập lệnh không có quyền thực thi và bạn không thể thay đổi nó, ví dụ: bằng cách chạy os.chmod('sleep.sh', 0o755)thì bạn có thể đọc tập lệnh dưới dạng tệp văn bản và chuyển chuỗi vào subprocessmô-đun thay thế:

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

33

Trên thực tế, bạn chỉ cần thêm shell=Trueđối số:

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

Nhưng hãy cẩn thận -

Cảnh báo Gọi shell hệ thống bằng shell = True có thể là một mối nguy hiểm về bảo mật nếu kết hợp với đầu vào không đáng tin cậy. Xem cảnh báo trong Đối số thường dùng để biết chi tiết.

nguồn


1
Nó sẽ không hoạt động nếu sleep.shkhông có trong PATH. Và nếu nó nằm trong đường dẫn và nó có shebang chính xác thì bạn không cần shell=True. Xem câu trả lời của tôi
jfs

16

Nếu ai đó đang tìm kiếm một tập lệnh có đối số

import subprocess

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

Hãy nhớ chuyển đổi args thành chuỗi trước khi chuyển, sử dụng str (arg).

Điều này có thể được sử dụng để chuyển nhiều đối số như mong muốn:

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

10

Đảm bảo rằng sleep.shcó quyền thực thi và chạy nó với shell=True:

#!/usr/bin/python

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

vì vậy nó là cái vỏ = Đúng là tôi đã bỏ lỡ. Bạn có thể giải thích, tại sao đặt #! Bin / bash trong dòng đầu tiên của sh scricpt là không đủ?
user1638145

3
Lỗi trong #!bin/bashlà thiếu /. #!/bin/bashhoạt động như tôi lưu ý trong một câu trả lời.
James Waldby - jwpat7

9

Nếu chmod không hoạt động thì bạn cũng thử

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

kiểm tra bởi tôi cảm ơn


Các os.systemtài liệu đặc biệt khuyên bạn tránh nó ủng hộ subprocess(những ngày này, subprocess.run()). Nếu bạn không thể subprocessđi làm, rất có thể bạn cũng sẽ gặp rắc rối os.system().
tripleee

3

Thêm câu trả lời vì tôi đã được hướng dẫn ở đây sau khi hỏi cách chạy tập lệnh bash từ python. Bạn gặp lỗi OSError: [Errno 2] file not foundnếu tập lệnh của bạn có tham số. Ví dụ, tập lệnh của bạn lấy tham số thời gian ngủ: subprocess.call("sleep.sh 10")sẽ không hoạt động, bạn phải chuyển nó dưới dạng một mảng:subprocess.call(["sleep.sh", 10])


Bạn phải hiểu ý nghĩa thực tế củashell=True nhưng có, thường thì tránh nó là cách chơi tốt nhất của bạn.
tripleee
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.