A. linux 系统怎么编写一个shell脚本,检查一个100台设备的是否都具有某项服务,如crond(定时任务
如何编写一个shell脚本
本文结合大量实例阐述如何编写一个shell脚本。
为什么要进行shell编程
在Linux系统中,虽然有各种各样的图形化接口工具,但是sell仍然是一个非常灵活的工具。Shell不仅仅是命令的收集,而且是一门非常棒的编程语言。您可以通过使用shell使大量的任务自动化,shell特别擅长系统管理任务,尤其适合那些易用性、可维护性和便携性比效率更重要的任务。
下面,让我们一起来看看shell是如何工作的:
建立一个脚本
Linux中有好多中不同的shell,但是通常我们使用bash (bourne again shell) 进行shell编程,因为bash是免费的并且很容易使用。所以在本文中笔者所提供的脚本都是使用bash(但是在大多数情况下,这些脚本同样可以在bash的大姐,bourne shell中运行)。
如同其他语言一样,通过我们使用任意一种文字编辑器,比如nedit、kedit、emacs、vi
等来编写我们的shell程序。
程序必须以下面的行开始(必须方在文件的第一行):
#!/bin/sh
符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。
当编辑好脚本时,如果要执行该脚本,还必须使其可执行。
要使脚本可执行:
chmod +x filename
然后,您可以通过输入: ./filename 来执行您的脚本。
B. Linux Shell 脚本编程最佳实践
IT路边社
前言
与其它的编码规范一样,这里所讨论的不仅仅是编码格式美不美观的问题, 同时也讨论一些约定及编码标准。这份文档主要侧重于我们所普遍遵循的规则,对于那些不是明确强制要求的,我们尽量避免提供意见。
编码规范对于程序员而言尤为重要,有以下几个原因:
本文档中的准则致力于最大限度达到以下原则:
尽管本文档涵盖了许多基础知识,但应注意的是,没有编码规范可以为我们回答所有问题,开发人员始终需要再编写完代码后,对上述原则做出正确的判断。
注 :未明确指明的则默认为必须(Mandatory)
主要参考如下文档:
仅建议Shell用作相对简单的实用工具或者包装脚本。因此单个shell脚本内容不宜太过复杂。
在选择何时使用shell脚本时时应遵循以下原则:
可执行文件不建议有扩展名,库文件必须使用 .sh 作为扩展名,且应是不可执行的。
执行一个程序时,无需知道其编写语言,且shell脚本并不要求具有扩展名,所以更倾向可执行文件没有扩展名。
而库文件知道其编写语言十分重要,使用 .sh 作为特定语言后缀的扩展名,可以和其他语言编写的库文件加以区分。
文件名要求全部小写, 可以包含下划线 _ 或连字符 - , 建议可执行文件使用连字符,库文件使用下划线。
正例:
反例:
源文件编码格式为UTF-8。避免不同操作系统对文件换行处理的方式不同,一律使用 LF 。
每行最多不超过120个字符。每行代码最大长度限制的根本原因是过长的行会导致阅读障碍,使得缩进失效。
除了以下两种情况例外:
如出现长度必须超过120个字符的字符串,应尽量使用here document或者嵌入的换行符等合适的方法使其变短。
示例:
除了在行结束使用换行符,空格是源文件中唯一允许出现的空白字符。
对从来没有用到的或者被注释的方法、变量等要坚决从代码中清理出去,避免过多垃圾造成干扰。
Bash 是唯一被允许使用的可执行脚本shell。
可执行文件必须以 #!/bin/bash 开始。请使用 set 来设置shell的选项,使得用 bash echo "Process $: Done making $$$."
# 示例7:命令参数及路径不需要引号 grep -li Hugo /dev/ "$1"
# 示例8:常规变量用双引号,ccs可能为空的特殊情况可不用引号 git send-email --to "${reviewers}" ${ccs:+"--cc" "${ccs}"}
# 示例9:正则用单引号,$1可能为空的特殊情况可不用引号 grep -cP '([Ss]pecial||?characters*) ${1:+"$1"}
# 示例10:位置参数传递推荐带引号的"$@",所有参数作为单字符串传递用带引号的"$*" # content of t.sh func_t { echo num: $# echo args: 1:$1 2:$2 3:$3 }
func_t "$@" func_t "$*" # 当执行 ./t.sh a b c 时输出如下: num: 3 args: 1:a 2:b 3:c num: 1 args: 1:a b c 2: 3:
使用 $(command) 而不是反引号。
因反引号如果要嵌套则要求用反斜杠转义内部的反引号。而 $(command) 形式的嵌套无需转义,且可读性更高。
正例:
反例:
条件测试
使用 [[ ... ]] ,而不是 [ , test , 和 /usr/bin/[ 。
因为在 [[ 和 ]] 之间不会出现路径扩展或单词切分,所以使用 [[ ... ]] 能够减少犯错。且 [[ ... ]] 支持正则表达式匹配,而 [ ... ] 不支持。参考以下示例:
尽可能使用变量引用,而非字符串过滤。
Bash可以很好的处理空字符串测试,请使用空/非空字符串测试方法,而不是过滤字符,让代码具有更高的可读性。正例:
反例:
正例:
反例:
正例:
反例:
文件名扩展
当进行文件名的通配符扩展时,请指定明确的路径。
当目录中有特殊文件名如以 - 开头的文件时,使用带路径的扩展通配符 ./* 比不带路径的 * 要安全很多。
应该避免使用eval。
Eval在用于分配变量时会修改输入内容,但设置变量的同时并不能检查这些变量是什么。反例:
请使用进程替换或者for循环,而不是通过管道连接while循环。
这是因为在管道之后的while循环中,命令是在一个子shell中运行的,因此对变量的修改是不能传递给父shell的。
这种管道连接while循环中的隐式子shell使得bug定位非常困难。反例:
如果你确定输入中不包含空格或者其他特殊符号(通常不是来自用户输入),则可以用for循环代替。例如:
使用进程替换可实现重定向输出,但是请将命令放入显式子 shell,而非 while 循环创建的隐式子 shell。例如:
总是检查返回值,且提供有用的返回值。
对于非管道命令,使用 $? 或直接通过 if 语句来检查以保持其简洁。
例如:
当内建命令可以完成相同的任务时,在shell内建命令和调用外部命令之间,应尽量选择内建命令。
因内建命令相比外部命令而言会产生更少的依赖,且多数情况调用内建命令比调用外部命令可以获得更好的性能(通常外部命令会产生额外的进程开销)。
正例:
反例:
加载外部库文件不建议用使用.,建议使用source,已提升可阅读性。正例:
反例:
除非必要情况,尽量使用单个命令及其参数组合来完成一项任务,而非多个命令加上管道的不必要组合。常见的不建议的用法例如:cat和grep连用过滤字符串; cat和wc连用统计行数; grep和wc连用统计行数等。
正例:
除特殊情况外,几乎所有函数都不应该使用exit直接退出脚本,而应该使用return进行返回,以便后续逻辑中可以对错误进行处理。正例:
反例:
推荐以下工具帮助我们进行代码的规范:
原文链接:http://itxx00.github.io/blog/2020/01/03/shell-standards/
获取更多的面试题、脚本等运维资料点击: 运维知识社区 获取
脚本之---短信轰炸机
脚本之---QQ微信轰炸机
ansible---一键搭建redis5.0.5集群
elk7.9真集群docker部署文档
全球最全loki部署及配置文档
最强安全加固脚本2.0
一键设置iptbales脚本
C. Linux如何编写shell脚本
一般以#!/bin/sh开头(不是必须要写,但一定要单独一行),指定执行这个脚本的shell程序(也可以用#!/bin/zsh或其他),然后就是堆命令了。
Linux的shell脚本支持很多功能,加上Linux高度模块化的命令,完全可以用shell脚本写出复杂的程序。
以上只是简单介绍如何开始写shell脚本,如果要写复杂的脚本,还需要深入学习相关知识(如if——fi、case——esac等结构)。
当然,还需要给脚本加上可执行权限(chmod +x ./file.sh),否则可以用sh ./file.sh方式执行脚本(这里的sh是执行脚本所需shell,命令也可以是zsh ./file.sh或其他)。
整个shell脚本,其实就相当于你在终端输入的一系列命令,如果想在shell里做什么,就先想想在终端可以做什么吧,字符的的连接,就是直接用 "" 双引号,输出,变量定义无 $ 符号,但是使用时一定要加上 $ 符号。
"=" 赋值符号,两边一定不能有空格,这和其他语言有区别,尤其是你还有自己代码美观风格时特别注意,否则会报语法错误!
for 中的数组内容是以 " " 空格分隔,而非 "," 逗号分格。
条件判断 [ true ] 中括号 后面需要有一个空格,但是两个中括号之间不能有空格如 [[ true ]]。
while 条件判断可以用 () 括号,也可以用 [[ ]] 中括号。
如果用windows写shell,一定要注意换行符格式 而非 , 需要借助一些编辑器(如notepad++)更改换行符格式!
D. 如何编写一个shell脚本
问题:
1、请求在线api, 获取json格式的返回结果
2、解析json里面的一个值
3、将该值存储到文件
开发准备:
1、shell
快速入门:
#!/bin/sh
cd ~
mkdir shell_tut
cd shell_tut
for ((i=0; i<10; i++)); do
touch test_$i.txt
done
创建一个文件夹, 并在里面新建10个文件
2、curl
使用curl请求网络, 并获取返回值
curl基本用法:
$ curl www.sina.com
直接返回网页内容
$ curl -o [文件名] www.sina.com
将网页内容存储到文件中, 相当于wget命令
赋值操作:
response=$(curl www.sina.com)
echo $response
注意: =前后没有空格
jq
jq是命令行解析json的很好的工具
安装
直接到官网下载Linux64版本(我是用本地下载好后传上服务器的, 之前直接在服务器用wget下载一直报错Segmentation fault, 折腾好久~)
将其到bin目录
cp jq-linux64 /usr/bin/jq
使用
然后就可以愉快的使用jq命令了:
可直接查看官网Tutorial
curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5'
返回的是一个json数组列表
curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.'
使用.直接指向json的根节点
curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.[0]'
[0]为取数组的第0位的对象
jq '.[0] | {message: .commit.message, name: .commit.committer.name}'
可用过连续的.操作获取对应json对象中的属性值, 上面的命令将会生成一个{message: "....", name: "...."}的json对象.
shell文件读写
1、写
方式一:
将ll的内容写入fileName这个文件中
>是覆盖, >>是在后面追加
ll >fileName
但是在书写.sh脚本的时候, 需要增加echo
echo ll>fileName
2、读
while read LINE
do
echo $LINE
done<fileName
fileName是即将读取的文件名
E. 如何在远程服务器上运行PowerShell命令
PowerShell在用户管理和维护Windows方面是一个强大的命令行环境。虽然PowerShell是一个本地管理工具,但是它也用于管理远程服务器。事实上,管理员可以针对大量的服务器创建PowerShell脚本来执行管理任务。Invoke-Command和New-PSSession都是在远程服务器中PowerShell的执行命令。
Invoke-Command
如果你只需要针对单台或者多台远程服务器执行一个命令(或者一系列的管道命令),那么最便利的方法就是使用Invoke-Command命令。Microsoft的文档列出了绝大多数的参数和语法,导致人人皆知Invoke-Command命令的复杂性。即使如此,使用Invoke-Command在远程系统上执行命令仍然出奇地容易。
对于基本的远程命令执行,你只需要提供远程计算机的名称和想要执行的代码块。假设你想要在名称为Proction1的远程服务器上执行Get-VM命令,你可以使用下面的命令:
Invoke-Command –ComputerName Proction1 {Get-VM}
虽然这看起来很简单,但是你也要对使用这个方法了解以下几点。
首先,Invoke-Command命令不限制你在一个远程系统上执行命令,你可以在多个计算机上指定命令,你需要做的就是使用命令区分开这些计算机的名称。例如,在Proction1,Proction2和Proction3计算机上执行命令如下:
Invoke-Command –ComputerName Proction1, Proction2, Proction3 {Get-VM}
第二点,你必须要知道虽然这个方式的设计目的只是简单地在单个远程系统上运行的单一命令,但是你也可以运行多个命令。如果查看之前的几行代码,你会注意到允许在远程计算机上运行的Get-VM命令是包含在花括号里面的。任何在花括号里面的命令都会在指定的远程计算机行运行。同样的,只要所有的命令都包含在花括号里面,你可以使用管道符号把命令把它们链接在一起。
第三点你必须知道上面的语法只有在所有计算机中使用了Kerberos认证才会运行,同时包括有命令输入和已经加入了域。否则,你必须使用HTTPS传输,并且必须指定远程系统是受信任的主机。