[英]Are there any modules to read shell scripts?
我現在正在制作python腳本,我需要使用在bash shell腳本中設置的一些環境變量。
bash腳本類似於:
#! /bin/sh
#sets some names:
export DISTRO="unified"
#export DISTRO="other"
#number of parallel builds
export BB_NUM_THREADS=2
#set build dir
export BUILDDIR=$PWD
通常,我只是在bash中獲取此腳本,然后進行構建。 我正在嘗試將python包裝在整個過程中,以對輸出進行一些管理,因此我想刪除手動source ./this_script.sh
步驟。
我想做的是從python讀取此腳本,然后使用os.environ
在其中設置變量。 (我知道這不會影響父對象,只會影響當前正在運行的Python實例,這樣就可以了)
為了使我的工作更輕松,我試圖找出是否有任何模塊可以“解析” bash腳本並利用其中的環境變量? 目前,我正在手動執行此操作,這有點痛苦。
如果沒有這樣的模塊可以完全實現我想要的功能,那么一般情況下,是否存在更多的pythonic(閱讀:更容易/更簡短)的方法來手動解析文件,現在我正在這樣做:
def parse_bash_script(fn):
with open(fn) as f:
for line in f:
if not line[:1] == '#': #ignore comments
if "export" in line:
line = line.replace(" ","").strip()
var = line[6:line.find("=")]
val = line[line.find("=")+1:len(line)]
if "\"" in val:
val = val[1:-1]
os.environ[var]=val
沒有模塊可以完全滿足您的需求,但是shlex
您的許多需求。 特別是,它將得到正確的引號等,而您不必擔心它(這是其中最難的部分)以及跳過注釋等。它唯一不會做的就是處理export
關鍵字。
解決這個問題的簡單方法是進行預處理:
with open(fn) as f:
processed = f.read().replace('export ', '')
for line in shlex.split(processed):
var, _, value = line.partition('=')
os.environ[var] = val
它有點hacker,但是您也可以通過后處理來減少冗長的操作。 特別地, shlex
將export foo="bar spam eggs"
視為兩個值: export
和foo="bar spam eggs"
,您可以跳過== 'export'
的分區,或者在分區找不到任何內容的地方,或者… 例如:
with open(fn) as f:
for line in shlex.split(f.read()):
var, eq, value = line.partition('=')
if eq:
os.environ[var] = val
如果您想變得更高級,可以構造一個shlex
對象,並(a)直接從文件驅動解析器,並且(b)在更細粒度的級別控制解析。 但是,我認為這不是必需的。
同時,如果您要處理環境替換(如BUILDDIR=$PWD
所暗示的),那么這將不會為您神奇地解決問題。 您可以使用它的ExtendedInterpolation
功能使configparser
做到這一點,但是隨后您將需要誘使configparser
處理shlex
語法,這時……何必麻煩。
當然,您可以通過編寫自己的插值器來手動完成此操作,但這很難做到。 您需要了解為什么$PWD-foo
與${PWD}-foo
,但是$PWD_foo
與${PWD_foo}
相同的shell規則。
在這一點上,一個更好的解決方案(假設腳本實際上可以安全運行)將是實際上使用shell為您完成此操作。 例如:
with open('script.sh') as f:
script = f.read()
script += b'\nenv'
with subprocess.Popen(['sh'], stdin=subprocess.PIPE, stdout=subprocess.PIPE) as p:
result = p.communicate(script)
for line in result.splitlines():
var, _, value = line.partition('=')
os.environ[var] = value
當然,這也會覆蓋_=/usr/bin/env
東西,但可能與您無關。
def parse_bash_script(fn):
with open(fn) as f:
for line in f:
if not line.startswith('#'): #ignore comments
if "export" in line:
var, _, val = line.partition('=')
var = var.lstrip()
val = val.rstrip()
if val.startswith('"'):
vals = val.rpartition('"')
val = vals[0][1]+vals[2]
os.environ[var]=val
我遇到了同樣的問題,並且根據abarnert的建議,我決定將解決方案作為對受限制的bash shell與shlex結合的子流程調用來實現。
import shlex
import subprocess
filename = '/path/to/file.conf'
o, e = subprocess.Popen(
['/bin/bash', '--restricted', '--noprofile', '--init-file',
filename, '-i', '-c', 'declare'],
env={'PATH': ''},
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).communicate()
if e:
raise StandardError('conf error in {}: {}'.format(filename, e))
for token in shlex.split(o):
parts = token.split('=', 1)
if len(parts) == 2:
os.environ[parts[0]] = parts[1]
受限Shell的優點在於,它可以阻止執行Shell腳本時可能發生的許多不良或惡意副作用。 從bash文檔中:
受限外殼用於設置比標准外殼更受控制的環境。 它的行為與bash相同,不同之處在於不允許或不執行以下操作:
- 用cd更改目錄
- 設置或取消設置SHELL,PATH,ENV或BASH_ENV的值
- 指定包含/的命令名稱
- 指定一個包含/的文件名作為。 內置命令
- 將包含斜杠的文件名指定為hash內置命令的-p選項的參數
- 啟動時從外殼環境導入函數定義
- 啟動時從shell環境中解析SHELLOPTS的值
- 使用>,> |,<>,>&,&>和>>重定向運算符重定向輸出
- 使用exec內置命令將外殼替換為另一個命令
- 在啟用內置命令中添加或刪除帶有-f和-d選項的內置命令
- 使用enable buildin命令啟用禁用的shell內置程序
- 在命令內置命令中指定-p選項
- 使用設置+ r或設置+ o限制關閉受限模式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.