教大家简单的 Shell 脚本入门操作
nanshan 2024-12-14 14:13 13 浏览 0 评论
Shell脚本 运作方式与解释型语言相当,如果有语言基础,学起 Shell 脚本就非常容易,但是 Shell 与常见的语言不同,一些常见的函数在 Shell 中需要组合一些命令得以实现
工具推荐
Shell 似乎没有定制的 IDE,这里推荐 VS Code 搭配对应的插件:
- shellman 智能提示和自动补全,在插件页面有介绍常用代码片段的触发关键词,作者在 Shellman reborn 中写到了 Shellman 诞生的故事,挺有趣的
- shellcheck 语法静态检查工具,插件安装后需要本地安装 shellcheck,参考 shellcheck Installing,Mac OS 可以使用 brew install shellcheck,这样在写 Shell 的时候,语法有误的地方就会以波浪线的方式提示
- shell-format 代码整理,Win 快捷键:Alt + Shift + F,Mac OS 快捷键:option + shift + F
- Code Runner 脚本运行,右键 Run Code,Win 快捷键:Ctrl + Alt + N,Mac OS 快捷键:control + option + N
运行 shell 脚本
新建脚本:test.sh
#!/usr/bin/env bash
# 使用echo 打印字符串或者变量
echo 'hello world'
可以用 Code Runner 运行,就会输出:hello world
在 Shell脚本 的第一行一般会写 #!/bin/bash 这个是 Shebang,#! 后面是解释器的绝对路径,脚本将用该解释器执行。还有一种写法是:#!/usr/bin/env bash,/usr/bin/env 是 env 命令的绝对路径,而 env 命令用于显示系统中已存在的环境变量,其中包含了 $PATH ,会在 $PATH 包含的目录依次找 bash,常见的命令行解释器有:sh ,bash ,zsh(Mac OS 默认解释器)
如果在 Linux 或 类Unix 下运行,有这么几种方式:
- 先给脚本添加执行权限:chmod +x test.sh,然后运行脚本:./test.sh,这种方式执行会读取 Shebang,用指定的解释器执行脚本
- sh test.sh,使用 sh 这个解释器执行脚本,当然也可以用其他方式执行,比如:bash test.sh。与第一种方式相同,当前的 shell 是父进程,生成一个子 shell 进程(子进程会继承父进程的环境变量),在子 shell 中执行脚本,脚本执行完毕,退出的 shell 回到当前 shell
- source 点命令方式:source test.sh 等效于 . test.sh。source 让脚本在当前 shell 执行,不生成新的子进程。使用 source 执行脚本,脚本中对于环境变量的修改会作用于当前 shell,这就是为什么我们在修改了一些配置如:~/.bashrc,执行 source ~/.bashrc 后配置就生效了
- exec 方式:有需要先给脚本添加执行权限:chmod +x test.sh,执行 exec ./test.sh,也是让脚本在同一个进程上执行不生成新的子进程,与 source 的区别就是,在脚本执行完成后进程会被结束
基础命令
可以按照 [Bash Shell] Shell学习笔记 学习,这篇文章讲得非常详细,本篇博客也是在学习这篇文章后写下的
获取输入
使用 read 命令,从标准输入流 (stdin) 获取输入
#!/usr/bin/env bash
read var
echo "${var}"
运行脚本,输入任意字符,回车确认,输入的值会赋值给变量 var,并打印出该变量
输出
#!/usr/bin/env bash
var=1
# 输出变量
echo ${var}
# 输出字符串 显示部分字符需要转义
echo "\"hello world\"" # "hello world"
# 换行使用 -e 参数:使转义字符生效
# 使用 \n 换行
echo -e "newline\n"
也可以让 shell 输出不同颜色的字符,可以参考:shell脚本中echo显示内容带颜色
#!/usr/bin/env bash
echo -e "\033[30m 黑色字 \033[0m"
echo -e "\033[31m 红色字 \033[0m"
echo -e "\033[32m 绿色字 \033[0m"
echo -e "\033[33m 黄色字 \033[0m"
echo -e "\033[34m 蓝色字 \033[0m"
echo -e "\033[35m 紫色字 \033[0m"
echo -e "\033[36m 天蓝字 \033[0m"
echo -e "\033[37m 白色字 \033[0m"
变量使用
# = 两边不能有空格
var="hello world"
num=100
# 在引用变量时,这种方式可以,但是推荐下面一种
echo $var
# 推荐在使用字符串变量时,在两侧加上双引号,否则如果变量字符串中存在空格,则字符串会被切分
echo "$var"
# 如果涉及字符串拼接,可以在变量名两侧加上花括号
echo "变量为: ${var}."
# 将变量设置为只读,再次修改会报错
readonly var
# var="wolrd"
# 删除变量,不能删除 readonly 修饰的变量
unset num
变量赋值时,变量名命名规则和其他语言类似,注意变量赋值时 = 两边不能有空格
使用时在变量名前加上 $,推荐所有的变量都使用 ${} 的方式使用变量
运算
算术运算:Bash 原生不支持数学运算,可以使用 awk 和 expr
注意乘号需要加上转义:\*,而且运算符两侧必须空格
a=10
b=3
val=`expr $a + $b`
echo "a + b : $val"
val=`expr $a - $b`
echo "a - b : $val"
val=`expr $a \* $b`
echo "a * b : $val"
val=`expr $b / $a`
echo "b / a : $val"
val=`expr $b % $a`
echo "b % a : $val"
执行命令
$()与 ``(反引号)都可以用于执行命令,并会将执行的结果返回,shellcheck 推荐使用第一种 $() 的方式
#!/usr/bin/env bash
result=`date "+%Y-%m-%d"`
echo "${result}"
result=$(date "+%Y-%m-%d")
echo "${result}"
运算符
关系运算符只支持数字,如果字符串为数字也可以,关系运算符包括:
运算符 | 含义 |
-eq | 等于 |
-ne | 不等于 |
-gt | 大于 |
-lt | 小于 |
-ge | 大等于 |
-le | 小等于 |
条件表达式必须放在 [] 中,并且 [ 的右侧,和 ] 的左侧必须留有空格
布尔运算符列表:
运算符 | 含义 |
! | 非 |
-o | 或 (or) |
-a | 与 (and) |
#!/usr/bin/env bash
a="10"
b="3"
c=1
if [ ${a} -ne ${b} ]
then
echo "相同"
else
echo "不相同"
fi
if [ ${a} -gt ${b} -a ${b} -gt ${c} ]
then
echo "a > b & b > c"
fi
其他常用判断:
- 直接在 [ ] 中放字符串变量 如 [ ${str} ] 则就是判断 str 这个字符串是否非空
- -f 判断是否为普通文件,如:[ -f $file ]
- -d 判断是否为文件夹,如:[ -d $file ]
字符串截取
字符截取的格式:${string: start :length}
索引从 0 开始,可以省略 :length 这样就截取到最后,注意空格要空在 : 后,否则可能提示:bad substitution
#!/usr/bin/env bash
string="hello world"
echo ${string: 1 : 3} # ell
# 截取到最后
echo ${string:1} # ello world
数组
#!/usr/bin/env bash
# 1. 定义数组:使用括号声明,用“空格”分隔开,也可以换行隔开
arr=(1 2 3)
strArr=(
"first"
"second"
)
# 2. 读取数组:通过下标读取,下标从 0 开始计算
echo "${arr[0]}"
# 使用 * 或者 @ 读取所有元素
echo ${arr[*]}
echo ${arr[@]}
# 读取数组长度 读取全部元素前面加上 #
echo ${#arr[*]}
echo ${#arr[@]}
# 遍历下标
for(( i=0;i<${#strArr[@]};i++))
do
echo ${strArr[i]};
done;
# for in 遍历元素
for element in ${strArr[*]}
do
echo $element
done
# 3. 修改数组元素
strArr[0]="modify"
echo ${strArr[0]}
# 4. 删除元素
unset arr[1]
echo ${#arr[*]}
echo ${arr[*]} # 1 3
# !使用 unset 要注意,这其实并不是真正删除了该元素,而只是将该元素置空,所以使用下标遍历会出问题,如下
echo "数组遍历:"
for(( i=0;i<${#arr[@]};i++))
do
echo "index ${i} -> ${arr[i]}";
done;
# index 0 -> 1
# index 1 ->
# 解决 unset 无法真正删除的方法:重新赋值给新的数组
echo "数组遍历:"
arr=( "${arr[@]}" )
for(( i=0;i<${#arr[@]};i++))
do
echo "index ${i} -> ${arr[i]}";
done;
# index 0 -> 1
# index 1 -> 3
判断语句
使用 if 和 fi 定义判断的边界,使用 then , elif , else 定义条件
#!/usr/bin/env bash
#!/usr/bin/env bash
a=10
b=20
if [ $a == $b ]
then
echo "相等"
else
echo "不相等"
fi
if [ $a == $b ]
then
echo "相等"
elif [ $a -lt $b ]
then
echo "a 小于 b"
else
echo "其他情况"
fi
函数
调用函数时,我们可以传入参数,可以通过 $n 来获取参数,这里的 n 表示 需要取的参数的索引,当n>=10时,需要使用${n}来获取参数
$# 传递给函数的参数个数,$* 和 $@ 显示所有传递给函数的参数,$? 表示函数的返回值,也可以用于获取上一个命令的退出状态,执行成功会返回 0,失败返回 1
# 定义函数
#!/usr/bin/env bash
funWithParam(){
echo "参数个数:$#" # 参数个数:11
echo "传递给函数的所有参数:$*" # 传递给函数的所有参数:1 2 3 4 5 6 7 8 9 34 73
echo "$1" # 1
# 超过 9 的参数需要用 ${} 接收参数,否则直接显示数值
echo "$10" # 10
echo "${11}" # 73
}
# 调用函数:函数名后面直接跟上参数
funWithParam 1 2 3 4 5 6 7 8 9 34 73
echo "$?" # 0
输入输出重定向
使用 > 将应该输出到终端上的数据重定向输出到文件,> 默认为覆盖文件,使用 >> 追加写入文件
使用 < 将默认从键盘输入的数据,定向为从文件输入
# who 命令用于显示系统中有哪些使用者正在上面
# 将结果输入 who.txt
who > who.txt
# wc -l 作用是计算文本行数
wc -l < who.txt
一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:
- 标准输入 (stdin):stdin 的文件描述符为 0,Unix 程序默认从 stdin 读取数据
- 标准输出 (stdout):stdout 的文件描述符为 1,Unix 程序默认向 stdout 输出数据
- 标准错误输出 (stderr):stderr 的文件描述符为 2,Unix 程序会向 stderr 流中写入错误信息
所以一般我们后台启动应用并且输出日志文件都使用:
nohup java -jar xxx.jar >> nohup.log 2>&1 &
nohup:(no hang up) 保证在退出帐户或者关闭终端之后继续运行相应的进程
>> nohup.log:将 java -jar xxx.jar 的输出追加到 nohup.log 文件
2>&1:将 java -jar xxx.jar 的 标准错误输出 也重定向到 标准输入
&:让进程在后台运行
默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
如果希望 stderr 重定向到 file,可以这样写:
坑梳理
- 变量赋值时,变量名命名规则和其他语言类似,注意变量赋值时 = 两边不能有空格
- 数组 unset 元素,并不是真正的移除元素
- 获取参数时,当 n>=10 时,需要使用${n}来获取参数
常见的特殊 Shell 环境变量
- $ 表示当前Shell进程的ID,即pid
- $0 表示当前脚本的绝对路径
- $# 传递给脚本或函数的参数个数
- $n 传递给脚本或函数的参数
- $? 上个命令的退出状态
- $* 和 $@ 传递给脚本或函数的所有参数
- $n n 代表 1~9 其中任意一个数字,传递给脚本或函数该位置的参数
$* 和 $@ 区别:
#!/usr/bin/env bash
function asterisk () {
echo "\"\$*\""
for var in "$*"
do
echo "$var"
done
}
function mail () {
echo "\"\$@\""
for var in "$@"
do
echo "$var"
done
}
asterisk a b c
mail a b c
输出
"$*"
a b c
"$@"
a
b
c
当 $* 和 $@ 直接使用效果相同,都是接收一份数据如上所示的例子,接收到的就是:a b c,一份数据,以空格隔开。加了双引号后 "$@" 会将每个参数都当成一份独立的数据
原文链接:https://www.cnblogs.com/aaronlinv/p/15764053.html
相关推荐
- 0722-6.2.0-如何在RedHat7.2使用rpm安装CDH(无CM)
-
文档编写目的在前面的文档中,介绍了在有CM和无CM两种情况下使用rpm方式安装CDH5.10.0,本文档将介绍如何在无CM的情况下使用rpm方式安装CDH6.2.0,与之前安装C5进行对比。环境介绍:...
- ARM64 平台基于 openEuler + iSula 环境部署 Kubernetes
-
为什么要在arm64平台上部署Kubernetes,而且还是鲲鹏920的架构。说来话长。。。此处省略5000字。介绍下系统信息;o架构:鲲鹏920(Kunpeng920)oOS:ope...
- 生产环境starrocks 3.1存算一体集群部署
-
集群规划FE:节点主要负责元数据管理、客户端连接管理、查询计划和查询调度。>3节点。BE:节点负责数据存储和SQL执行。>3节点。CN:无存储功能能的BE。环境准备CPU检查JDK...
- 在CentOS上添加swap虚拟内存并设置优先级
-
现如今很多云服务器都会自己配置好虚拟内存,当然也有很多没有配置虚拟内存的,虚拟内存可以让我们的低配服务器使用更多的内存,可以减少很多硬件成本,比如我们运行很多服务的时候,内存常常会满,当配置了虚拟内存...
- 国产深度(deepin)操作系统优化指南
-
1.升级内核随着deepin版本的更新,会自动升级系统内核,但是我们依旧可以通过命令行手动升级内核,以获取更好的性能和更多的硬件支持。具体操作:-添加PPAs使用以下命令添加PPAs:```...
- postgresql-15.4 多节点主从(读写分离)
-
1、下载软件[root@TX-CN-PostgreSQL01-252software]#wgethttps://ftp.postgresql.org/pub/source/v15.4/postg...
- Docker 容器 Java 服务内存与 GC 优化实施方案
-
一、设置Docker容器内存限制(生产环境建议)1.查看宿主机可用内存bashfree-h#示例输出(假设宿主机剩余16GB可用内存)#Mem:64G...
- 虚拟内存设置、解决linux内存不够问题
-
虚拟内存设置(解决linux内存不够情况)背景介绍 Memory指机器物理内存,读写速度低于CPU一个量级,但是高于磁盘不止一个量级。所以,程序和数据如果在内存的话,会有非常快的读写速度。但是,内存...
- Elasticsearch性能调优(5):服务器配置选择
-
在选择elasticsearch服务器时,要尽可能地选择与当前业务量相匹配的服务器。如果服务器配置太低,则意味着需要更多的节点来满足需求,一个集群的节点太多时会增加集群管理的成本。如果服务器配置太高,...
- Es如何落地
-
一、配置准备节点类型CPU内存硬盘网络机器数操作系统data节点16C64G2000G本地SSD所有es同一可用区3(ecs)Centos7master节点2C8G200G云SSD所有es同一可用区...
- 针对Linux内存管理知识学习总结
-
现在的服务器大部分都是运行在Linux上面的,所以,作为一个程序员有必要简单地了解一下系统是如何运行的。对于内存部分需要知道:地址映射内存管理的方式缺页异常先来看一些基本的知识,在进程看来,内存分为内...
- MySQL进阶之性能优化
-
概述MySQL的性能优化,包括了服务器硬件优化、操作系统的优化、MySQL数据库配置优化、数据库表设计的优化、SQL语句优化等5个方面的优化。在进行优化之前,需要先掌握性能分析的思路和方法,找出问题,...
- Linux Cgroups(Control Groups)原理
-
LinuxCgroups(ControlGroups)是内核提供的资源分配、限制和监控机制,通过层级化进程分组实现资源的精细化控制。以下从核心原理、操作示例和版本演进三方面详细分析:一、核心原理与...
- linux 常用性能优化参数及理解
-
1.优化内核相关参数配置文件/etc/sysctl.conf配置方法直接将参数添加进文件每条一行.sysctl-a可以查看默认配置sysctl-p执行并检测是否有错误例如设置错了参数:[roo...
- 如何在 Linux 中使用 Sysctl 命令?
-
sysctl是一个用于配置和查询Linux内核参数的命令行工具。它通过与/proc/sys虚拟文件系统交互,允许用户在运行时动态修改内核参数。这些参数控制着系统的各种行为,包括网络设置、文件...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- linux 查询端口号 (58)
- docker映射容器目录到宿主机 (66)
- 杀端口 (60)
- yum更换阿里源 (62)
- internet explorer 增强的安全配置已启用 (65)
- linux自动挂载 (56)
- 禁用selinux (55)
- sysv-rc-conf (69)
- ubuntu防火墙状态查看 (64)
- windows server 2022激活密钥 (56)
- 无法与服务器建立安全连接是什么意思 (74)
- 443/80端口被占用怎么解决 (56)
- ping无法访问目标主机怎么解决 (58)
- fdatasync (59)
- 405 not allowed (56)
- 免备案虚拟主机zxhost (55)
- linux根据pid查看进程 (60)
- dhcp工具 (62)
- mysql 1045 (57)
- 宝塔远程工具 (56)
- ssh服务器拒绝了密码 请再试一次 (56)
- ubuntu卸载docker (56)
- linux查看nginx状态 (63)
- tomcat 乱码 (76)
- 2008r2激活序列号 (65)