<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          用Python寫個Linux系統(tǒng)命令

          共 5176字,需瀏覽 11分鐘

           ·

          2020-06-23 23:25

          這篇文章介紹如何寫個系統(tǒng)命令以及我為什么要寫命令

          “一切皆文件”是linux的基本哲學之一,我們在linux下執(zhí)行的諸如ls之類的命令實際上都是去執(zhí)行了系統(tǒng)上的某個文件,which命令可以查看到我們執(zhí)行的命令對應(yīng)的是系統(tǒng)上的哪個文件,例如常用的ls命令實際上就是執(zhí)行了/bin/ls這個文件

          root@ops-coffee:~#?which?ls
          /bin/ls

          基于此,我們就知道了定義一個命令很簡單,只需要寫個可執(zhí)行的文件就行了,python的標準模塊argparse就可以幫助我們快速方便的構(gòu)建一個用戶友好的命令

          argparse

          相比于自己實現(xiàn)個命令文件,argparse模塊能夠自動生成幫助和使用手冊,并在用戶傳入無效參數(shù)時報錯。一個簡單的示例如下

          #!/usr/bin/env?python3
          #?coding:utf8

          import?argparse

          parser?=?argparse.ArgumentParser(description='整數(shù)處理')
          parser.add_argument('integers',?type=int,?help='要處理整數(shù)')

          args?=?parser.parse_args()
          print(args.integers)

          這個示例的意思是接收一個數(shù)字,并將這個數(shù)字輸出,接下來看一下詳細的解釋

          首先創(chuàng)建了一個ArgumentParser對象,ArgumentParser對象有很多參數(shù)可以選擇,這里的description定義在參數(shù)幫助文檔之前顯示的文本,通常用來定義這個程序做什么以及怎么做

          parser?=?argparse.ArgumentParser(description='整數(shù)處理')

          然后通過add_argumentArgumentParser對象添加參數(shù),第一個參數(shù)integers為參數(shù)名,type指定類型為inthelp指定這個字段的幫助信息

          parser.add_argument('integers',?type=int,?help='要處理的整數(shù)')

          通過調(diào)用ArgumentParser對象的parse_args方法返回一個具有所有參數(shù)屬性的對象

          args?=?parser.parse_args()

          最后通過args.參數(shù)名獲取到傳入的參數(shù)值

          print(args.integers)

          執(zhí)行

          我們將以上文件命名為opscoffee,并賦予執(zhí)行權(quán)限,放在系統(tǒng)環(huán)境變量/bin下,就可以當作命令直接執(zhí)行了

          #?chmod?+x?opscoffee
          #?mv?opscoffee?/bin/

          如果直接執(zhí)行opscoffee命令的話將會收到一個報錯,提示你必須有一個參數(shù)integers

          #?opscoffee
          usage:?opscoffee?[-h]?integers
          opscoffee:?error:?the?following?arguments?are?required:?integers

          同時也通過usage告訴了你這個命令的用法,默認有一個-h參數(shù)可以打印命令幫助

          #?opscoffee?-h
          usage:?opscoffee?[-h]?integers

          整數(shù)處理

          positional?arguments:
          ? integers ???要處理的整數(shù)

          optional?arguments:
          ??-h,?--help??show?this?help?message?and?exit

          這就是使用argparse模塊的好處,自動生成幫助,提供友好的使用體驗

          參數(shù)

          argparse能實現(xiàn)的遠不止于此,還有更加強大的功能,主要在于add_argument方法參數(shù)的運用,以下以一些例子來學習下一些常用的參數(shù)

          可選參數(shù)

          當我們在參數(shù)名前添加-或者--時,argparse會默認認為這是一個可選參數(shù),可以不傳值,例如

          parser.add_argument('--age',?type=int,?help='年齡')

          可選參數(shù)當沒有傳值時的默認值為None,可以通過default來設(shè)置默認值

          parser.add_argument('--age',?type=int,?default=37,?help='年齡')

          當沒有參數(shù)--age時,顯示default設(shè)置的值(沒有設(shè)置default則顯示None),有--age則顯示--age指定的值

          #?opscoffee
          37
          #?opscoffee?--age?38
          38

          如果你想讓可選參數(shù)也變成必選的,則只需要設(shè)置required=True即可

          parser.add_argument('--age',?type=int,?default=37,?required=True,?help='年齡')

          type

          type用來指定參數(shù)的類型,允許任何類型檢查和類型轉(zhuǎn)換,例如strintfloatopen甚至是你自定義的方法都可以。

          #!/usr/bin/env?python3
          #?coding:utf8

          import?argparse

          def?even(string):
          ????value?
          =?int(string)

          ????if?value%2!=0:
          ????????msg?=?"%r?不是偶數(shù)"?%?string
          ????????raise?argparse.ArgumentTypeError(msg)
          ????return?value

          parser?=?argparse.ArgumentParser(description='整數(shù)處理')
          parser.add_argument('integers',?type=even,?help='要處理的整數(shù)')

          args?=?parser.parse_args()
          print(args.integers)

          以上命令接收一個參數(shù)integers,并將其type設(shè)置為了自定義方法even,這個方法會判斷用戶輸入的數(shù)字是否是偶數(shù),如果不是則報錯,執(zhí)行結(jié)果如下

          #?opscoffee?1
          usage:?opscoffee?[-h]?integers
          opscoffee:?error:?argument?integers:?'1'?不是偶數(shù)
          #?opscoffee?2
          2

          choices

          choices參數(shù)可以限制參數(shù)的范圍,例如我們只想讓用戶從opscoffee兩個參數(shù)中選擇一個輸入,則可以這樣用

          parser.add_argument('site',?choices=['ops','coffee'],?help='Site')

          那么當我們輸入的內(nèi)容不是opscoffee時,則報錯

          #?opscoffee?cn
          usage:?opscoffee?[-h]?{ops,coffee}
          opscoffee:?error:?argument?site:?invalid?choice:?'cn'?(choose?from?'ops',?'coffee')

          nargs

          通常我們在argparse中定義的參數(shù)數(shù)量與傳入的參數(shù)數(shù)量應(yīng)當相等,但有些時候我們需要接收未知數(shù)量的參數(shù),nargs就可以幫助我們

          nargs支持以下值:N(整數(shù))、'?''*''+'argarse.REMAINDER

          N: 表示N個參數(shù)會被聚集到一個列表中,例如

          import?argparse

          parser?=?argparse.ArgumentParser(description='整數(shù)處理')
          parser.add_argument('integers',?type=int,?nargs=2,?help='要處理的整數(shù)')

          args?=?parser.parse_args()
          print(args.integers)

          將輸出

          #?opscoffee?9?10?
          [9,?10]

          '?': 表示使用一個或不使用參數(shù),當不傳參數(shù)時,默認為None

          parser.add_argument('integers',?type=int,?nargs='?',?help='要處理的整數(shù)')

          '*': 表示使用所有參數(shù),參數(shù)個數(shù)可以為0

          parser.add_argument('integers',?type=int,?nargs='*',?help='要處理的整數(shù)')

          '+':'*'類似,但至少要有一個參數(shù),否則將會報錯

          parser.add_argument('integers',?type=int,?nargs='+',?help='要處理的整數(shù)')

          自定義命令

          先說我為什么要寫個系統(tǒng)命令?

          文章『Probius:一個功能強大的自定義任務(wù)系統(tǒng)』中介紹了我們的自定義任務(wù)系統(tǒng),這個系統(tǒng)可以用來編排任務(wù),而在編排CICD任務(wù)中會用到配置文件,我們的配置文件都是通過Kerrigan配置中心來管理的,目前獲取配置中心的配置主要有兩種方法

          1. ?配合confd服務(wù)自動拉取更新,詳細內(nèi)容可以查看這篇文章:中小團隊落地配置中心詳解


          2.? 配置中心提供API,可以通過API獲取配置內(nèi)容

          腳本里如果想要使用配置中心的配置,則只能通過API的方式去獲取,這樣就要在每個需要用到配置的地方寫一段代碼來獲取及處理,不僅會出現(xiàn)大量的重復代碼,并且非常的不優(yōu)雅,更為重要的是請求API的Token將會出現(xiàn)在腳本里,帶來一定的安全風險

          基于以上考慮,寫個自定義命令來做這件事情更為妥當,于是便寫了下邊這個命令

          #!/usr/bin/env?python3
          #?coding:utf8

          #?這是一個系統(tǒng)命令用來獲取kerrigan配置中心的配置并寫入本地文件,需要將此文件copy到目錄/bin下

          import?sys
          import?argparse
          import?requests

          parser?=?argparse.ArgumentParser(description='獲取配置中心Kerrigan配置')

          parser.add_argument('configkey',?type=str,?help='配置中心中文件的Key')
          parser.add_argument('localfile',?type=str,?help='保存到本地文件的路徑')

          args?=?parser.parse_args()

          #?獲得傳入的參數(shù)
          configkey?=?args.configkey
          localfile?=?args.localfile

          header?=?{
          ????'Authorization':?'Token?eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.JTdCJTIyZXhwJTIyJTNBMTkwNjcwNzAyMCUyQyUyMmlhdCUyMiUzQTE1OTEzNDcwMjAlMkMlMjJkYXRhJTIyJTNBJTdCJTIydXNlcm5hbWUlMjIlM0ElMjJwcm9iaXVzQG9wcy1jb2ZmZWUuY24lMjIlN0QlN0Q.ops1ZNhq19XSEL2PUo-iQqzbhimDnpFiYc_7EUXftF4'}

          uri?=?'http://kerrigan.ops-coffee.cn/api/config/?key='?+?configkey
          r?=?requests.get(uri,?headers=header)

          if?r.json()['state']:
          ????content?=?r.json()['message']['content']

          ????try:
          ????????with?open(localfile,?'w')?as?f:
          ????????????f.write(content)

          ????????sys.exit(0)
          ????except?Exception?as?e:
          ????????print('write?local?file?failed:?',?str(e))
          ????????sys.exit(3)
          else:
          ????print('get?config?failed:?',?r.json()['message'])
          ????sys.exit(1)

          以上代碼的意思是根據(jù)傳入的key和file路徑,去配置中心獲取對應(yīng)配置文件的內(nèi)容并寫入到本地file中。需要注意的是exit,返回合適的退出狀態(tài)是個很好的習慣,這樣我們就可以通過$?來獲取命令執(zhí)行成功還是失敗

          將此文件命名為getconfig并移動到/bin目錄下添加執(zhí)行權(quán)限,就可以在系統(tǒng)任何地方使用getconfig命令了

          # getconfig?/conf/coffee/prod/docker/Dockerfile??/home/project/coffee/Dockerfile
          瀏覽 89
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  六月婷婷五月丁香 | 在线黄片观看 | 免费看肏屄 | 嫩草综合网 | 欧美黄色成人视频 |