Linux系统下用python写程序,用Python写个Linux系统命令

这篇文章介绍如何写个系统命令以及我为什么要写命令

“一切皆文件”是linux的基本哲学之一,我们在linux下执行的诸如ls

之类的命令实际上都是去执行了系统上的某个文件,which

命令可以查看到我们执行的命令对应的是系统上的哪个文件,例如常用的ls

命令实际上就是执行了/bin/ls

这个文件root@ops-coffee:~# which ls/bin/ls

基于此,我们就知道了定义一个命令很简单,只需要写个可执行的文件就行了,python的标准模块argparse

就可以帮助我们快速方便的构建一个用户友好的命令

argparse

相比于自己实现个命令文件,argparse

模块能够自动生成帮助和使用手册,并在用户传入无效参数时报错。一个简单的示例如下#!/usr/bin/env python3# coding:utf8import argparseparser = argparse.ArgumentParser(description='整数处理')parser.add_argument('integers', type=int, help='要处理整数')args = parser.parse_args()print(args.integers)

这个示例的意思是接收一个数字,并将这个数字输出,接下来看一下详细的解释

首先创建了一个ArgumentParser

对象,ArgumentParser

对象有很多参数可以选择,这里的description

定义在参数帮助文档之前显示的文本,通常用来定义这个程序做什么以及怎么做parser = argparse.ArgumentParser(description='整数处理')

然后通过add_argument

给ArgumentParser

对象添加参数,第一个参数integers

为参数名,type

指定类型为int

,help

指定这个字段的帮助信息parser.add_argument('integers', type=int, help='要处理的整数')

通过调用ArgumentParser

对象的parse_args

方法返回一个具有所有参数属性的对象args = parser.parse_args()

最后通过args.参数名

获取到传入的参数值print(args.integers)

执行

我们将以上文件命名为opscoffee

,并赋予执行权限,放在系统环境变量/bin

下,就可以当作命令直接执行了# chmod +x opscoffee# mv opscoffee /bin/

如果直接执行opscoffee

命令的话将会收到一个报错,提示你必须有一个参数integers# opscoffeeusage: opscoffee [-h] integersopscoffee: error: the following arguments are required: integers

同时也通过usage

告诉了你这个命令的用法,默认有一个-h

参数可以打印命令帮助# opscoffee -husage: opscoffee [-h] integers整数处理positional arguments:  integers    要处理的整数optional arguments:  -h, --help  show this help message and exit

这就是使用argparse

模块的好处,自动生成帮助,提供友好的使用体验

参数

argparse

能实现的远不止于此,还有更加强大的功能,主要在于add_argument

方法参数的运用,以下以一些例子来学习下一些常用的参数

可选参数

当我们在参数名前添加-

或者--

时,argparse

会默认认为这是一个可选参数,可以不传值,例如parser.add_argument('--age', type=int, help='年龄')

可选参数当没有传值时的默认值为None

,可以通过default

来设置默认值parser.add_argument('--age', type=int, default=37, help='年龄')

当没有参数--age

时,显示default

设置的值(没有设置default

则显示None),有--age

则显示--age

指定的值# opscoffee37# opscoffee --age 3838

如果你想让可选参数也变成必选的,则只需要设置required=True

即可parser.add_argument('--age', type=int, default=37, required=True, help='年龄')

type

type

用来指定参数的类型,允许任何类型检查和类型转换,例如str

、int

、float

、open

甚至是你自定义的方法都可以。#!/usr/bin/env python3# coding:utf8import argparsedef even(string):    value= int(string)    if value%2!=0:        msg = "%r 不是偶数" % string        raise argparse.ArgumentTypeError(msg)    return valueparser = argparse.ArgumentParser(description='整数处理')parser.add_argument('integers', type=even, help='要处理的整数')args = parser.parse_args()print(args.integers)

以上命令接收一个参数integers

,并将其type

设置为了自定义方法even

,这个方法会判断用户输入的数字是否是偶数,如果不是则报错,执行结果如下# opscoffee 1usage: opscoffee [-h] integersopscoffee: error: argument integers: '1' 不是偶数# opscoffee 22

choices

choices

参数可以限制参数的范围,例如我们只想让用户从ops

或coffee

两个参数中选择一个输入,则可以这样用parser.add_argument('site', choices=['ops','coffee'], help='Site')

那么当我们输入的内容不是ops

或coffee

时,则报错# opscoffee cnusage: opscoffee [-h] {ops,coffee}opscoffee: error: argument site: invalid choice: 'cn' (choose from 'ops', 'coffee')

nargs

通常我们在argparse

中定义的参数数量与传入的参数数量应当相等,但有些时候我们需要接收未知数量的参数,nargs

就可以帮助我们

nargs支持以下值:N

(整数)、'?'

、'*'

、'+'

、argarse.REMAINDER

N: 表示N个参数会被聚集到一个列表中,例如import argparseparser = argparse.ArgumentParser(description='整数处理')parser.add_argument('integers', type=int, nargs=2, help='要处理的整数')args = parser.parse_args()print(args.integers)

将输出# opscoffee 9 10[9, 10]

'?': 表示使用一个或不使用参数,当不传参数时,默认为Noneparser.add_argument('integers', type=int, nargs='?', help='要处理的整数')

'*': 表示使用所有参数,参数个数可以为0parser.add_argument('integers', type=int, nargs='*', help='要处理的整数')

'+': 与'*'

类似,但至少要有一个参数,否则将会报错parser.add_argument('integers', type=int, nargs='+', help='要处理的整数')

自定义命令

先说我为什么要写个系统命令?

文章『Probius:一个功能强大的自定义任务系统』中介绍了我们的自定义任务系统,这个系统可以用来编排任务,而在编排CICD任务中会用到配置文件,我们的配置文件都是通过Kerrigan配置中心来管理的,目前获取配置中心的配置主要有两种方法

1.  配合confd服务自动拉取更新,详细内容可以查看这篇文章:中小团队落地配置中心详解

2.  配置中心提供API,可以通过API获取配置内容

脚本里如果想要使用配置中心的配置,则只能通过API的方式去获取,这样就要在每个需要用到配置的地方写一段代码来获取及处理,不仅会出现大量的重复代码,并且非常的不优雅,更为重要的是请求API的Token将会出现在脚本里,带来一定的安全风险

基于以上考虑,写个自定义命令来做这件事情更为妥当,于是便写了下边这个命令#!/usr/bin/env python3# coding:utf8# 这是一个系统命令用来获取kerrigan配置中心的配置并写入本地文件,需要将此文件copy到目录/bin下import sysimport argparseimport requestsparser = argparse.ArgumentParser(description='获取配置中心Kerrigan配置')parser.add_argument('configkey', type=str, help='配置中心中文件的Key')parser.add_argument('localfile', type=str, help='保存到本地文件的路径')args = parser.parse_args()# 获得传入的参数configkey = args.configkeylocalfile = args.localfileheader = {    'Authorization': 'Token eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.JTdCJTIyZXhwJTIyJTNBMTkwNjcwNzAyMCUyQyUyMmlhdCUyMiUzQTE1OTEzNDcwMjAlMkMlMjJkYXRhJTIyJTNBJTdCJTIydXNlcm5hbWUlMjIlM0ElMjJwcm9iaXVzQG9wcy1jb2ZmZWUuY24lMjIlN0QlN0Q.ops1ZNhq19XSEL2PUo-iQqzbhimDnpFiYc_7EUXftF4'}uri = 'http://kerrigan.ops-coffee.cn/api/config/?key=' + configkeyr = 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)

以上代码的意思是根据传入的key和file路径,去配置中心获取对应配置文件的内容并写入到本地file中。需要注意的是exit

,返回合适的退出状态是个很好的习惯,这样我们就可以通过$?

来获取命令执行成功还是失败

将此文件命名为getconfig并移动到/bin目录下添加执行权限,就可以在系统任何地方使用getconfig

命令了# getconfig /conf/coffee/prod/docker/Dockerfile  /home/project/coffee/Dockerfile

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值