標籤:

python好庫之sh

python好庫之sh

來自專欄 python取經小分隊

一直以來linux命令也只是用到時去查一下, 但是當看到比較大的bash 腳本時就有點畏縮了,但是在linux下工作調用命令還是必須的,終於找到一種解決方案,通過sh可以像調用函數一樣調用linux下系統命令.

先看一段shell腳本:

對於bash的一些語法斷斷續續看過一點,但是時間一長就給忘記了. 像上面的腳本看懂總是有點累啊,而且不是那麼pythonic. 下面就開始介紹一下可以用python去寫bash的方式.

sh庫簡介

sh將系統的命令動態映射到python函數,通過python的方式去寫shell腳本.

安裝

pip install sh

基本使用

(1)獲取網路介面信息:

import shprint sh.ifconfig("eth0")# 或者from sh import ifconfigprint ifconfig("eth0")

輸出:

eth0 Link encap:Ethernet HWaddr 00:16:3e:00:13:d7 inet addr:10.162.223.199 Bcast:10.162.223.255 Mask:255.255.240.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:71475 errors:0 dropped:0 overruns:0 frame:0 TX packets:78854 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:51051493 (51.0 MB) TX bytes:6101887 (6.1 MB)

(2)列印目錄信息:

sh.ls("/home", "-l")

輸出:

total 8drwxr-xr-x 2 root root 4096 Nov 4 10:52 a-rw-r--r-- 1 root root 88 Nov 4 10:54 a.txt

關鍵字參數

當命令里需要參數時,sh調用表現方式會像你期望的一樣.下面是一個下載頁面到本地文件的命令:

curl https://www.baidu.com -o page.html --silent

對應的sh方式為:

sh.curl("https://www.baidu.com", o="page.html", silent=True)

查找命令

可以利用which檢測命令是否存在:

>>> sh.which("python") /usr/bin/python>>> print sh.which("ls") /bin/ls

安裝不存在命令:

if not sh.which("supervisorctl"): sh.apt_get("install", "supervisor", "-y")

烘焙(Baking)

其實就是類似於函數綁定,將參數綁定到函數上.

from sh import lsls = ls.bake("-la")print(ls("/home")) # 這樣默認就加上了選項-la

輸出為:

total 16drwxr-xr-x 3 root root 4096 Nov 4 10:54 .drwxr-xr-x 22 root root 4096 Oct 11 17:34 ..drwxr-xr-x 2 root root 4096 Nov 4 10:52 a-rw-r--r-- 1 root root 88 Nov 4 10:54 a.txt

例子

下面簡單去實現一個例子(安裝nginx並啟動),更直觀的看到sh的便利(環境含有pip):

# -*- coding: utf8 -*-import subprocessdef install_sh(): try: retcode = subprocess.call("pip install sh", shell=True) return retcode except OSError as e: return "Execution failed:", etry: import shexcept ImportError: install_sh() import sh# ps -auxc | grep nginxdef is_nginx_running(): r = sh.grep(sh.ps("-auxc"), "nginx", _ok_code=[1, 2, 3]) return r.exit_code == 0def install_nginx(): if not sh.which("nginx"): print "nginx not exist, will install" sh.apt_get("install", "nginx", "-y") else: print "nginx has installed"def start_nginx(): r = sh.service("nginx", "start", _ok_code=[1, 2, 3]) if r.exit_code == 0: print "start success" else: print "start failed"if __name__ == "__main__": if not is_nginx_running(): install_nginx() start_nginx() else: print "nginx is running"

可以點擊這裡下載

原理

一開始我還以為sh里實現了像ls、curl等命令,當打開源碼才發現是沒有的. 那麼當執行sh.ls時為何沒報錯呢?下面來探索一下:

在python中有一種我們不常用的類型ModuleType. 如下:

>>> import types >>> types.ModuleType<type module>

我們導入的模塊都是module這種類型. 下面演示一下sh的基本實現:

import sysfrom types import ModuleTypeclass SelfWrapper(ModuleType): def __init__(self, self_module): self.self_module = self_module def __getattr__(self, name): return "fetch command:", nameif __name__ == "__main__": passelse: self = sys.modules[__name__] sys.modules[__name__] = SelfWrapper(self)

這裡是將導入的模塊替換為我們自己定義的模塊. 將上面代碼保存為sh_test.py,然後就可以使用:

>>> import sh_test>>> print sh_test.ls(fetch command:, ls)

當我們去訪問模塊不存在的屬性是,會調用__getattr__方法. 這只是簡單的分析了一下sh基本原理, 更多的可以自己去看源碼source

參考

  • how-to-use-sh-in-python

  • sh

  • 分析一個python庫--sh

推薦閱讀:

在Bash中按Ctrl-S為什麼會失去響應?
什麼是 .bashrc,為什麼要編輯 .bashrc? | Linux 中國
4 種繞過 Linux/Unix 命令別名的方法
Linux編程之變數1:bash變數與變數分類-1
如何評價 Windows 版「bash」(及其相關 *nix 子系統)?

TAG:Python | Bash |