Linux操作系统是一种开放源代码的类UNIX
操作系统,它的结构分为内核
、Shell
和应用程序
三个层次。
命令行解释器
,它负责将用户输入的命令解释并执行
Bash Shell
命令行解释器
脚本语言
,可以通过编写一系列的命令和脚本来执行操作系统的功能和任务Bourne Shell(/bin/sh)
:是Unix系统最早
的shell程序,由史蒂夫·伯恩斯(Steve Bourne)编写。该shell程序是许多Linux发行版中默认使用的程序Bourne-Again SHell(/bin/bash)
:是GNU项目的一部分,是Bourne Shell的增强版,目前在大部分Linux发行版中是默认
的shell程序C Shell (/bin/csh)
:是Bill Joy编写的一个具有面向对象设计理念的shell程序,它采用与C语言相似的语法和控制结构。C Shell中的命令提示符为%号TENEX C Shell(/bin/tcsh)
:是C Shell的增强版,它对历史命令和别名等方面进行了改进,同时也支持C Shell中的所有特性。TENEX C Shell中的命令提示符也为%号Korn Shell(/bin/ksh)
:是由David Korn编写的shell程序,它是Bourne Shell和C Shell的结合,拥有两种不同的工作模式:交互模式和批处理模式Z Shell(/bin/zsh)
:是一个功能强大
的shell程序,它是Bourne Shell的增强版,具有缩写、自动完成、句法高亮等功能,同时也支持Korn Shell、C Shell以及Bourne Shell的语法和命令每种Shell都有其特定的语法和功能,但它们通常都具有共同的基本功能,如变量操作、条件语句、循环语句和命令执行等。
查看已安装的Shell
cat /etc/shells
查看当前Shell(查看$SHELL环境变量
)
echo $SHELL
更改Shell(需要重启服务
)
chsh -s /bin/sh
xxx.sh
结尾的文件中,xxx.sh文件我们称为shell脚本文件
可执行文件
,类似于windows环境中的xxx.exe或xxx.bat等文件 在Shell脚本中,注释是用来解释代码的内容,Shell脚本中的注释使用#
符号表示,任何在#
后面的内容都会被Shell解释器忽略。
单行注释(用#
开头的内容作为注释)
# 这是一个单行注释
echo "Hello, World!" # 这也是一个注释
echo
命令用于在终端上输出文本或变量的值,主要用于显示信息
或调试脚本
多行注释(可以通过连续的#
来实现多行注释)
# 这是一个多行注释
# 它可以扩展到
# 多行
也可以用以下形式:
: '
这是一个多行注释
它使用 : 和单引号来包裹
解释器会忽略这些内容
'
示例
一个简单的脚本文件
#!/bin/bash
在 Shell 脚本的第一行,表示该脚本应该用哪个解释器运行
可以省略
,如果省略会使用当前会话的默认shell解释器
#!/bin/bash
# 打印 "Hello, World!"
echo "Hello, World!"
查看文件权限(默认没有执行权限)
修文件权限(添加执行权限)
chmod +x script.sh
# 或者
chmod 744 script.sh
执行文件
./script.sh
本地变量
是指在某个脚本
或函数
的作用范围内定义的变量,只能在该作用范围内访问。本地变量的生命周期仅限于创建它的脚本或函数,执行完毕后,变量会自动销毁
本地变量命名规则
字母
、数字
和下划线
组成(字母一般是小写
,环境变量用大写)示例
双引号
允许引用变量,变量会被解析单引号
不会解析变量,原样输出#!/bin/bash
name="Alice"
echo "Hello, $name" # 输出:Hello, Alice
echo 'Hello, $name' # 输出:Hello, $name
系统配置信息
或用户定义的信息
全部大写
,单词和单词之间采用下划线分割
。如:0JAVA_HOME, CATALINA_HOMEShell会话外设置
的,可以由多个脚本和进程共享
常见的环境变量
变量名 | 说明 |
---|---|
PATH | 指定系统查找可执行文件的路径(如/usr/bin:/bin:/usr/local/bin) |
HOME | 当前用户的主目录路径(如/root) |
USER | 当前用户名(如root) |
PWD | 当前工作目录路径(如/root/test) |
SHELL | 当前用户使用的默认 Shell(如/bin/bash) |
LANG | 系统语言和字符编码信息(如 en_US.UTF-8) |
TERM | 当前终端的类型(如xterm-256color) |
LOGNAME | 当前登录的用户名(如root) |
查看当前所有环境变量
printenv
# 或者
env
查看或使用某个环境变量(使用环境变量,在变量名称前必须加上$
符号)
echo $PATH
在脚本中直接访问环境变量
#!/bin/bash
echo "当前用户是:$USER"
echo "主目录是:$HOME"
当前会话中有效
,会话结束后失效export
设置环境变量基本语法
export 变量名=值
示例:
export MY_VAR="Hello World"
echo $MY_VAR
环境变量中多个值使用:
分隔符
export CLASSPATH=/lib:/usr/lib:/home/user/myapp/lib
# 通过 PATH 的已有值加上新路径
export PATH=$PATH:/new/path
配置文件
中添加到
用户
配置文件
将环境变量添加到~/.bashrc
或~/.bash_profile
中(针对 Bash Shell)
export JAVA_HOME=/usr/local/java/jdk1.8.0_371
export PATH=$JAVA_HOME/bin:$PATH
重新加载配置文件
source ~/.bashrc
添加到系统
全局
配置文件
将环境变量添加到/etc/profile
中(对所有用户生效)
export JAVA_HOME=/usr/local/java/jdk1.8.0_371
export PATH=$JAVA_HOME/bin:$PATH
重新加载配置文件
source /etc/profile
预定义
的变量名称,具有特殊的含义常见特殊变量
$0
: 当前脚本的文件名$#
: 脚本参数的数量$*
: 所有脚本参数的列表 $@
: 所有脚本参数的列表 $$
: 当前脚本的进程ID号$?
: 上一个命令的退出状态,一个数值 $!
:后台运行的最后一个进程的进程ID本地变量命名规则
script.sh
#!/bin/bash
# 脚本名
echo "脚本名称: $0"
# 参数个数
echo "参数总数: $#"
# 打印所有参数
echo "所有参数 (\$@): $@"
echo "所有参数 (\$*): $*"
# 第一个和第二个参数
echo "第一个参数: $1"
echo "第二个参数: $2"
# 当前脚本的 PID
echo "当前脚本的 PID: $$"
# 执行一个后台命令
sleep 5 &
echo "最后一个后台进程的 PID: $!"
# 判断上一个命令是否执行成功
echo "上一个命令执行成功 (返回值: $?)"
# 执行一个错误命令测试返回值
ls /nonexistent/path &>/dev/null
echo "错误命令返回非零值 (返回值: $?)"
./script.sh arg1 arg2 arg3
运行脚本,输出如下:基本语法
if condition
then
command1
command2
...
elif condition2
then
command3
command4
...
else
command5
command6
...
fi
示例:
#!/bin/bash
if [ -f file.txt ]
then
echo "file.txt文件存在"
elif [ -d dir ]
then
echo "dir目录存在"
else
echo "file.txt and dir都没找到"
fi
基本语法
for var in list
do
command1
command2
...
done
其中,var是一个临时的变量名,用于存储当前循环的值,list是一个值或者多个带有空格
或换行符分隔
的值组成的列表。
示例:
#!/bin/bash
for i in 1 2 3 4 5
do
echo "The value of i is: $i"
done
基本语法
while condition
do
command1
command2
...
done
在shell编程中((...))被称为算术扩展运算符,做数学运算的,并且将运算结果返回。(...)运算符会将结果直接返回
示例:
#!/bin/bash
j=0
while [ $j -lt 5 ]
do
echo "The value of j is: $j"
j=$((j+1))
done
until循环用于不断执行语句块,直到满足指定条件为止。和while循环相反,while是直到指定条件为假时才会停止循环。
基本语法
until condition
do
command1
command2
...
done
示例:
#!/bin/bash
k=0
until [ $k -ge 5 ]
do
echo "The value of k is: $k"
k=$((k+1))
done
break语句用于跳出当前循环块
,例如在for循环和while循环中使用该语句时,可以跳出当前循环并停止迭代。
continue语句用于跳过本次循环
迭代,直接进入下一次的迭代。
示例:
#!/bin/bash
for l in 1 2 3 4 5
do
if [ $l -eq 3 ]
then
continue
fi
echo "The value of l is: $l"
if [ $l -eq 4 ]
then
break
fi
done
输出结果(等于3跳过,等于4跳出循环结束)
1
2
在Shell脚本中,函数是一种封装代码
的方式,可以提高代码的重用性和可读性。
基本语法
function_name() {
# 函数体:执行的命令或脚本
}
或者:
function function_name() {
# 函数体:执行的命令或脚本
}
示例
say_hello() {
echo "Hello, World!"
}
# 调用函数
say_hello
函数可以通过位置参数(1, 2, …)接收输入参数,类似于脚本中的参数。
示例
greet() {
echo "Hello, $1! Welcome to $2."
}
# 调用函数并传递参数
greet "Alice" "Linux"
说明:
空格分隔
如果希望在 任何地方都可以调用函数,可以将函数定义放入Shell的配置文件中,例如~/.bashrc
或~/.zshrc
。
方法
编辑 ~/.bashrc(或 ~/.zshrc),添加函数定义
greet() {
echo "Hello, $1!"
}
保存文件后,运行以下命令重新加载配置
source ~/.bashrc
现在,你可以在任何命令行终端调用该函数
greet "Alice"
# 1. 定义服务端口
port=1514
# 2. 查找并杀掉正在运行的进程
pid=$(lsof -t -i:$port)
if [ -n "$pid" ]; then
echo "杀掉$port端口进程"
kill -9 $pid
else
echo "没有端口为$port的进程"
fi
# 3. 启动新进程
cd /data/java
nohup java -jar my-springboot.jar > /data/log/boot.log 2>&1 &
echo "$port端口的服务已重启"
在Linux系统中,运行Shell脚本(如 .sh
文件)有多种方式。以下是常见的几种执行方式及它们的区别。
基本语法
sh script.sh
或者
bash script.sh
特点
sh
或 bash
)执行权限
,只要有读权限
即可步骤
给脚本赋执行权限
chmod +x script.sh
直接运行脚本
./script.sh
或者完整路径
/path/to/script.sh
特点
#!/bin/bash
解释器运行,如果没有使用当前Shell默认解释器执行权限
语法
. script.sh
或者
source script.sh
特点
执行权限
,只要有读权限
即可 如果希望脚本在任何地方都可以运行,可以将脚本文件放入$PATH
中的目录(如/usr/local/bin
或~/bin
)
示例
将脚本移动到系统目录
mv script.sh /usr/local/bin
确保脚本可执行
chmod +x /usr/local/bin/script.sh
直接调用脚本
script.sh