4月7日没参加体侧的我自学shell的第一天
Shebang
计算机程序中,shebang指的是出现在文本文件的第一行前两个字符 #!
1)以#!/bin/sh 开头的文件,程序在执行的时候会调用/bin/sh, 也就是bash解释器
2)以#!/usr/bin/python 开头的文件, 代表指定python 解释器去执行
3)以#!/usr/bin/env 解释器名称, 是一种在不同平台上都能正确找到解释器的办法
# 输出变量的值
echo $SHELL
写一个简单的Python编译器的shell脚本
#! /usr/bin/python
# coding:utf-8
print("你好!")
# 如果解释器坏了,或者不能正确运行,就手动指定解释器,这里我的shell脚本的名称为hello.py
/usr/bin/python hello.py
脚本注释,脚本开发规范
1)在shell脚本中,#后面的内容代表注释掉的内容,提供给开发者或使用者观看,系统会忽略此行
2)注释可以单独写,也可以跟在命令后面
3)保持爱写注释的习惯,以便于以后回顾代码的含义,尽量使用英文
执行shell脚本的方式
1)bash script.sh 或 sh script.sh, 文件本身没有执行权限或没有写shebang,则使用的方法
2)使用 绝对/相对 路径执行脚本, 需要文件含有x权限(chmod +x 文件名)
3) source script.sh 或 . script.sh , 代表 执行的含义, source 等于点
4)少见的用法, sh < script.sh
什么是bash
1)bash是一个命令处理器, 运行在文本窗口中,并能执行用户直接输入的命令
2)bash还能从文件中读取Linux命令,称之为脚本
3)bash支持通配符、管道、命令替换、条件判断等逻辑控制语句
bash有诸多方便的功能,有助于运维人员提升工作效率
# history命令
-c 清空历史
-r 恢复历史
# 调用历史记录命令
# 感叹号+历史命令行ID
!! # 执行上一行命令,以及上下左右寻找
变量
特殊的变量,用于检测上一行的代码是否成功运行。
echo $?
0 # 表示运行成功
1-255 # 表示运行失败
注意:
单引号变量,不识别特殊语法
双引号变量,能识别特殊符号
eg.演示单引号,双引号的区别
name=“奥利给”
echo ${name}
>> 奥利给
name2='${name}'
>> ${name}
name3="${name}"
>> 奥利给
1)每次调用bash/sh解释器执行脚本,都会开启一个子shell,因此不保留当前的shell变量,通过pstree命令检查进程树
2)调用source或者点符号是在当前shell环境加载脚本,因此保留变量
反引号的用法
name=`ls`
# 先会执行ls命令然后再把结果赋值给name
环境变量
1)每个用户都有自己的环境变量配置文件
~/.bash_profile ~/.bashrc
且以个人配置文件,优先加载变量,读取,以个人的优先生效
2)当你需要给所有用户都使用某个变量,写入全局即可/etc/profile
set # 输出所有变量,包括全局变量,局部变量(sh中定义的变量)
set |grep ^name # 用于查询指定的变量,此处是查询以name开头的变量。
set |wc -l # 用于统计全局变量的个数
env # 只显示系统的全局变量
declare # 输出所有的变量,如同set
export # 显示和设置环境变量的值
# 撤销环境变量
unset 变量名 # 用于删除变量或函数。
# 设置只读变量
readonly name='hello'
name='hi~'
>> -bash: name: 只读变量
系统保留环境变量关键字
bash内嵌套了诸多环境变量,用于定义bash的工作环境
export |awk -F '[ :=]' '{print $3}'
# 用于只显示系统环境变量的名称
bash支持多命令执行
ls /data/; cd/tmp/; cd /home; cd / data
特殊变量
参数传递:
$0 # 获取shell脚本文件名,以及路径
$n # 获取shell脚本的第n个参数,n在1~9之间,如$1, $2, $9,大于9则需要写,${10},参数空格隔开
$# # 获取执行shell脚本后面的参数总个数
$* # 获取shell脚本所有参数,不加引号等同于$@作用,加上引号"$*"作用是接收所有参数为单个字符串,“$1 $2..
$@ # 不加引号,效果同上,加引号,是接收所有参数为独立字符串,如“$1” "$2" "$3" ..., 空格保留
案例演示:我先新建了一个名为 special_var.sh的shell脚本
#!/bin/bash
echo '特殊变量 $0 $1 $2 ..的实践' # 单引号就是远洋输出
echo '结果:' $0 $1 $2
echo '----------------------'
echo '特殊变量获取$# 获取参数总个数'
echo '结果:' $#
echo '----------------------'
echo '特殊变量$* 实践'
echo '结果:' $*
echo '----------------------'
echo '特殊变量$@ 实践'
echo '结果:' $@
效果如下:
bash special_var.sh li hao 2021 2022 2023 2024
>>
特殊变量 $0 $1 $2 ..的实践
结果:special_var.sh li hao
-----------------------
特殊变量获取$# 获取参数总个数
结果:6
-----------------------
特殊变量$* 实践
结果:li hao 2021 2022 2023 2024
-----------------------
特殊变量$@ 实践
结果:li hao 2021 2022 2023 2024
面试题分析
$* 与 $@的区别?
$* 和 $@ 都表示传递给函数或脚本的所有参数
当$* 和 $@ 不被双引号包裹时,效果都是一样,都是将所有的参数当成一个整体输出,彼此之间空格隔开
但当他们被双眼号包“”裹的时候,就有区别了:
"$*" 会把所有的参数从整体上来看当成一份数据,而不是把每一个参数都看做一份数据
"$@" 会把每一个参数单独对待,当成一个个不同的数据
在for循环中证明了"$*"和"$@"的区别
"$*"--》li hao 2024 2025 (只循环一次)
"$@" (把所有的数据都循环一遍,一共循环了4次)
--》
li
hao
2024
2025
案例体验:
我创建了一个名为different.sh 的shell脚本
#!/bin/bash
echo "print each param from \"\$*\""
for var in "$*"
do
echo "$var"
done
echo "print each param from \"\$@\""
for var in "$@"
do
echo "$var"
done
效果如下:
bash different.sh li hao 2024 2025
>>
print each param from "$*"
li hao 2024 2025
print each param from "$@"
li
hao
2024
2025
特殊状态变量
$? # 上一次命令执行状态返回值,0正确,非0失败
$$ # 当前shell脚本的进程号
$! # 上一次后台进程的PID
$_ # 查看之前执行的命令,最后一个参数
脚本返回值,在学习shell函数编程之后,才能彻底理解,这个脚本在执行完毕后会返回一个数字ID,称之为返回值
案例:
首先我创建了一个名为t1.sh的shell脚本
cat t1.sh
#!/bin/bash
# $#获取参数个数 -ne 不等于的情况 && 并且的意思
[ $# -ne 2 ] && {
echo "must be two args"
exit 119
# 终止程序运行,且返回119状态码,提供给当前shell的$?变量,若是在函数里 可以return 119的用法
}
echo "没毛病,就是2个参数"
效果如下:
bash t1.sh li hao 2024
>>must be two args
echo $?
119
bash t1.sh li hao
没毛病,就是2个参数
echo $?
>>0
面试题
怎样让程序在后台执行?
nohup xxx & 1> /dev/null
获取上次后台运行的PID,$!
nohup ping baidu.com & 1> /dev/null
>>[1] 21973
ps -ef|grep ping # 在所有正在运行的进程中查看包含ping的进程
>> root 21973 20999 0 16:34 pts/0 00:00:00 ping baidu.com
echo $!
>> 21973
获取当前的脚本ID
cat t1.sh
#!/bin/bash
# $#获取参数个数 -ne 不等于的情况 && 并且的意思
[ $# -ne 2 ] && {
echo "must be two args"
exit 119
# 终止程序运行,且返回119状态码,提供给当前shell的$?变量,若是在函数里 可以return 119的用法
}
echo "没毛病,就是2个参数"
echo "当前的脚本ID是:$$"
运行效果如下:
bash t1.sh li hao
>> 没毛病,就是2个参数
>> 当前的脚本ID是:20001 # 每次运行完成后的脚本ID都不一样
$_获取上一次命令传入的最后一个参数
bash t1.sh li hao
...
echo $_
>> hao