一站式Shell编程攻略:从入门到精通
一、Shell编程简介
1.1 Shell的定义与功能
Shell是一种命令行解释器,是在计算机操作系统中提供用户与操作系统交互的一种方式。通常Shell是指命令行界面,用户通过Shell界面可以输入命令并获得相应的操作结果。
Shell的主要功能包括:
- 解释和执行用户输入的命令:用户可以通过Shell界面输入各种命令,Shell会将这些命令解释并执行相应的操作。例如,用户可以输入ls命令来查看当前目录下的文件列表。
- 管理和控制进程:Shell可以启动、停止、暂停和重启进程,还可以查看和管理当前正在运行的进程。例如,用户可以通过Shell启动一个后台进程,或者通过Shell杀死一个卡死的进程。
- 文件和目录管理:Shell可以对文件和目录进行各种操作,如创建、删除、复制、移动、重命名等等。用户可以通过Shell在文件系统中进行各种操作。
- 系统管理:Shell还可以管理和配置系统设置、环境变量、网络配置等等。例如,用户可以通过Shell配置网络连接,修改系统环境变量等等。
1.1.1 Shell的作用
Shell的主要作用有以下几个方面:
- 提供命令行界面:Shell提供了一个命令行界面,用户可以通过键盘输入命令来与操作系统进行交互。这种交互方式相对于图形用户界面更加高效,可以让用户快速地完成各种操作。
- 管理文件和目录:Shell可以对文件和目录进行各种操作,如创建、删除、复制、移动、重命名等等。用户可以通过Shell在文件系统中进行各种操作,例如创建文件夹、查看文件内容、修改文件权限等。
- 执行各种命令和程序:用户可以通过Shell执行各种命令和程序,如编译代码、运行脚本、启动服务等。Shell会将用户输入的命令解释并执行相应的操作。
- 管理进程和系统资源:Shell可以管理和控制进程,包括启动、停止、暂停和重启进程,还可以查看和管理当前正在运行的进程。同时,Shell还可以管理系统资源,如内存、CPU等。
- 配置系统和环境:Shell可以管理和配置系统设置、环境变量、网络配置等等。用户可以通过Shell配置网络连接,修改系统环境变量等等。
1.1.2 常见的Shell类型
- Bourne Shell(sh):Bourne Shell是Unix操作系统中最早的Shell,由Stephen Bourne开发。它是大多数Unix系统中默认的Shell,也是其他Shell的基础。Bourne Shell是一种比较简单的Shell,常用于编写Shell脚本和自动化任务。
- C Shell(csh):C Shell由Bill Joy开发,是一种比较高级的Shell。它具有C语言风格的语法和交互式命令历史功能,可以方便地编写复杂的Shell脚本和交互式应用程序。C Shell通常用于编写交互式应用程序和系统管理任务。
- Korn Shell(ksh):Korn Shell是由AT&T Bell实验室的David Korn开发的一种Shell,它是Bourne Shell的升级版,具有更加强大的编程功能。Korn Shell支持数组、函数、变量替换和命令行编辑等高级功能,也是Shell脚本编程中常用的一种Shell。
- Bash Shell(bash):Bash Shell是Bourne Again Shell的缩写,是由Brian Fox和Chet Ramey共同开发的一种Shell。它是Bourne Shell的增强版,与Bourne Shell基本兼容,但是具有更多的功能和特性,包括命令补全、历史命令、别名等。
常见的Shell类型包括Bourne shell(/bin/sh)、Bash shell(/bin/bash)等。其中,Bash shell是Linux系统中应用最广泛的Shell类型,也是默认的Shell类型。
1.2 Shell脚本的基本结构
一般情况下,Shell脚本以文本文件的形式存在。Shell脚本由若干条命令和控制结构组成,可以在命令行中直接执行,也可以在脚本中进行批量处理。
1.2.1 Shebang解释器声明
Shebang是指在Unix或Linux系统中,位于脚本文件的第一行,以"#"和"!"两个字符组成的特殊语法。例如,#!/bin/bash就是一条Shebang语法,指示操作系统用bash解释器来执行后续的脚本命令。
通俗地说,Shebang就是一种告诉操作系统如何解释执行脚本文件的语法。当操作系统执行一个脚本文件时,会首先读取文件的第一行,如果第一行以Shebang语法开头,就会根据指定的解释器来执行脚本文件中的命令。
在Linux系统中,Shebang语法通常用于指定脚本的解释器类型,如bash、sh、python等等。它的作用是确保脚本文件能够在正确的环境中被执行,从而保证脚本的正确性和可靠性。
从专业角度来讲,Shebang是一种在脚本文件中添加特殊标记以指定解释器类型的机制。在文件系统中,每个文件都有一个类型标识和可执行属性,而Shebang就是一种特殊的类型标识,它指定了脚本文件的解释器类型,使得系统可以正确地识别和执行脚本文件。除了指定解释器类型外,Shebang还可以添加参数和选项,以更加精确地控制脚本的执行行为。
简短的讲,Shebang是指以"#!"开头的一行注释,它告诉系统使用哪个解释器来执行这个文件。在Linux中,常见的Shebang声明包括:
#!/bin/bash # 使用Bash shell解释器
#!/usr/bin/python3 # 使用Python 3解释器
1.2.2 注释和文档
Shell脚本中使用#符号来表示注释,注释可以用于说明脚本的功能、参数含义等相关信息。另外,Shell脚本还可以通过"Here Document"结构来定义多行文档:
#!/bin/bash
这是一个Shell脚本示例
作者:张三
日期:2023-04-26
EOF
1.2.3 可执行权限与执行方式
为了让Shell脚本能够像普通命令那样执行,必须为其添加可执行权限。在终端中使用chmod命令来修改文件的权限:
chmod +x script.sh
然后就可以通过"./script.sh"或者"sh script.sh "等方式来执行Shell脚本。
二、基本语法与命令
2.1 变量与数据类型
在Bash中,变量可以用来存储任意类型的数据。变量名由字母、数字和下划线组成,不能以数字开头。变量的赋值需要使用等号(=)操作符,等号两端不能有空格。例如:
name="John"
age=25
2.1.1 变量定义与赋值
变量的定义和赋值可以在一行完成,也可以分开进行。如果变量的值包含空格或其他特殊字符,需要使用引号将其括起来。例如:
greeting="Hello World"
count=10
result=$((count + 5)) # 这里使用了算术表达式$(())
2.1.2 变量引用与拓展
在Bash中,可以通过在变量名前加上“$”符号来引用变量。例如:
echo $name
# 输出 John
还可以在变量名前加上“${}”来对变量进行拓展,以实现更高级的替换功能。例如:
echo ${greeting} # 输出 Hello World
echo ${greeting/World/Universe} # 输出 Hello Universe
2.1.3 环境变量
环境变量是一种全局变量,可以在整个系统中被访问和修改。在Bash中,可以使用“export”命令将一个变量声明为环境变量。例如:
export PATH=/usr/local/bin:$PATH
2.2 控制结构
2.2.1 条件判断
在Bash中,可以使用“if”结构进行条件判断。其中,“fi”表示条件结束。例如:
if [ $count -eq 10 ]; then
echo "Count is 10"
elif [ $count -gt 10 ]; then
echo "Count is greater than 10"
echo "Count is less than 10"
fi
在上面的例子中,使用了“[ ]”来进行条件测试,其中“-eq”表示相等,“-gt”表示大于。
2.2.2 循环结构
在Bash中,可以使用“for”和“while”结构进行循环操作。例如:
# for 循环
for i in {1..5}; do
echo $i
# while 循环
count=0
while [ $count -lt 5 ]; do
echo $count
count=$((count + 1))
done
2.3 基本命令
2.3.1 文件操作
在Bash中,有许多命令可以用于文件操作。例如:
# 创建目录
mkdir mydir
# 删除文件或目录
rm myfile
rm -r mydir
# 复制文件或目录
cp file1 file2
cp -r dir1 dir2
# 移动文件或目录
mv file1 file2
mv dir1 dir2
2.3.2 文本处理
在Bash中,可以使用文本处理命令来对文本文件进行操作。例如:
# 查看文件内容
cat myfile
# 查找文本
grep pattern myfile
# 替换文本
sed 's/pattern/replacement/g' myfile
sort myfile
2.3.3 系统管理
在Bash中,可以使用系统管理命令来管理系统状态和配置。例如:
# 查看进程状态
ps aux
# 查看系统资源使用情况
# 查看网络连接状态
netstat -a
# 修改文件权限
chmod 755 myfile
下面是一个简单的表格,展示了一些常用的 Linux 命令及其用途:
分类 | 命令 | 用途 | 示例 |
---|---|---|---|
文件操作 | ls | 列出当前目录下的文件和子目录 | ls -l /path/to/directory |
文件操作 | cd | 改变当前工作目录 | cd /path/to/directory |
文件操作 | pwd | 显示当前工作目录的路径 | pwd |
文件操作 | mkdir | 创建一个新目录 | mkdir newdirectory |
文件操作 | rm | 删除一个文件或目录 | rm file.txt 或 rm -r directory |
文件操作 | cp | 复制一个文件或目录 | cp sourcefile destinationfile 或 cp -r sourcedir destinationdir |
文件操作 | mv | 移动或重命名一个文件或目录 | mv oldname newname 或 mv olddir newdir |
文件操作 | touch | 创建一个新文件或更新一个已存在文件的时间戳 | touch newfile.txt |
文件查看 | cat | 连接文件并打印到标准输出 | cat file.txt |
文件查看 | less | 分页查看文本文件的内容 | less file.txt |
文本处理 | grep | 在文件中搜索指定的字符串 | grep pattern file.txt |
文件查找 | find | 查找文件或目录 | find / -name filename.txt |
文件压缩 | tar | 打包、压缩和解压文件和目录 | tar -cvzf archive.tar.gz directory/ 或 tar -xvzf archive.tar.gz |
文件下载 | wget | 下载文件 | wget https://example.com/file.zip |
远程访问 | ssh | 远程登录到另一个计算机 | ssh username@hostname |
远程复制 | scp | 在本地主机和远程主机之间复制文件 | scp file.txt username@hostname:/remote/directory |
权限管理 | chmod | 修改文件权限 | chmod u=rw,go=r file.txt |
用户管理 | chown | 更改文件所有者 | chown username file.txt |
进程管理 | ps | 列出运行中的进程 | ps -e |
进程管理 | kill | 终止一个正在运行的进程 | kill PID |
系统监控 | top | 实时显示系统资源使用情况 | top |
三、函数与模块化
3.1 函数的定义与调用
在Bash中,可以使用“function”关键字或者省略关键字的方式来定义函数。例如:
3.1.1 函数定义
# 使用 function 关键字定义函数
function myfunc {
echo "Hello from myfunc"
# 省略 function 关键字
myfunc() {
echo "Hello from myfunc"
}
3.1.2 函数调用
函数调用时需要使用函数名和参数列表(如果有的话),参数之间用空格分隔。例如:
myfunc arg1 arg2
3.2 函数参数与返回值
3.2.1 传递参数
在Bash中,可以通过位置变量来传递参数。例如,$1 表示第一个参数,$2 表示第二个参数,以此类推。例如:
myfunc() {
echo "Hello $1 and $2"
myfunc Alice Bob
上面的代码输出:
Hello Alice and Bob
在函数内部也可以使用特殊变量 $@ 或 $* 来获取所有传递的参数。例如:
myfunc() {
echo "Arguments: $@"
myfunc Alice Bob Charlie
上面的代码输出:
Arguments: Alice Bob Charlie
3.2.2 返回值
在Bash中,函数返回值可以使用“return”命令来设置,返回值为一个非负整数。例如:
myfunc() {
return 10
myfunc
echo "Return value: $?"
上面的代码输出:
Return value: 10
3.3 模块化编程
3.3.1 脚本分离
在Bash中,可以将脚本分解成多个文件,以实现模块化编程。例如,将一个函数定义保存在名为“ lib.sh ”的文件中:
# 文件名:lib.sh
myfunc() {
echo "Hello from myfunc"
}
然后在另一个脚本中导入该文件并调用函数:
# 文件名:main.sh
source lib.sh
myfunc
运行“ main.sh ”脚本即可输出:
Hello from myfunc
3.3.2 模块导入与使用
在Bash中,可以通过“source”或“.”命令来导入其他脚本或库文件。例如:
source lib.sh
或者:
. lib.sh
这样就可以在当前脚本中使用被导入脚本中定义的函数和变量了。
四、错误处理与调试
4.1 错误处理与调试
在Bash中,常见的错误包括语法错误、运行时错误和逻辑错误。下面分别介绍。
4.1.1 语法错误
语法错误通常是指脚本中出现了不符合 Bash 语法规范的语句,例如缺少引号、括号不匹配、变量名错误等等。这些错误会导致脚本无法正常执行。为了避免语法错误,可以使用 ShellCheck 等工具来检查代码。
4.1.2 运行时错误
运行时错误通常是指脚本在执行过程中出现了问题,例如文件不存在、权限不足、内存不足等等。为了避免这些错误,可以在脚本中使用条件语句进行判断,以确保程序能够正确地运行。同时,还可以使用 try-catch 或者 trap 命令来捕捉和处理异常。
4.1.3 逻辑错误
逻辑错误通常是指脚本的输出结果和预期不一致,例如变量赋值错误、循环条件错误、函数调用错误等等。为了避免逻辑错误,可以在编写脚本时进行严格的测试和校验,以确保程序的正确性。
4.2 调试技巧与工具
4.2.1 输出调试
在 Bash 中,可以使用 echo 命令输出调试信息来查看程序的执行情况。例如:
echo "Start of program"
myfunc
echo "End of program"
4.2.2 使用
set
命令
在 Bash 中,可以使用 set -x 命令来打开调试模式,这样所有执行的语句都会被输出到终端上。例如:
set -x
myfunc
set +x
4.2.3 使用调试器
Bash 提供了内置的调试器——bashdb,它可以帮助我们更方便地调试 Bash 脚本。
首先需要安装 bashdb,例如在 Ubuntu 系统上可以使用以下命令进行安装:
sudo apt-get install bashdb
然后在脚本文件中添加以下代码:
#!/bin/bash -x
# 这里是脚本内容
myfunc
最后运行以下命令即可进入调试模式:
bashdb myscript.sh
在调试模式下,可以使用类似 gdb 的命令来逐步执行脚本、查看变量值等等。
示例:
假设有一个名为
myscript.sh
的 Bash 脚本,需要进行调试。该脚本的内容如下:
bash#!/bin/bash
echo "Starting the script..."
for i in {1..10}
if (( $i % 2 == 0 ))
echo "$i is even"
echo "$i is odd"
echo "Script completed."
这个脚本会输出从 1 到 10 的数字,并判断它们是奇数还是偶数。现在,我们想要使用
bashdb
来调试此脚本。
首先,我们需要安装
bashdb
。在 Ubuntu 系统中,可以使用以下命令来安装:
sudo apt-get install bashdb
安装完成后,我们可以使用以下命令启动
bashdb
:
bashdb myscript.sh
然后,
bashdb
将会显示与脚本相关的一些信息,并等待用户输入命令。接下来,我们可以使用
bashdb
提供的命令逐步执行脚本,并查看变量的值和程序流程。
例如,我们可以使用
b
命令设置断点,然后使用
r
命令运行脚本,在遇到断点时停止。
bashdb$ b 7
Breakpoint 1 at file myscript.sh, line 7
bashdb$ r
Starting the script...
现在,脚本已经运行到第 7 行,并停在了断点处。我们可以使用
n
命令逐行执行代码,并使用
p
命令打印变量的值。
bashdb$ n
for i in {1..10}
Breakpoint 1, file myscript.sh, line 7
bashdb$ p i
No value for i
bashdb$
我们注意到,在第 7 行
i
的值还没有被赋值。我们可以继续使用
n
命令执行下一行,或者使用
s
命令进入函数或子程序中。
当脚本完全执行完毕时,我们可以使用
q
命令退出
bashdb
。
五、实用技巧与最佳实践
5.1 编码规范与风格
5.1.1 代码可读性
在编写 Bash 脚本时,应该尽可能提高代码的可读性。可以通过以下方式实现:
- 使用注释来解释代码的作用和逻辑;
- 使用空格、缩进等排版符号来使代码更易读;
- 将代码分解成函数或模块以提高代码的重用性。
5.1.2 统一风格
在多人协作开发时,为了避免出现代码混乱不统一的情况,应该制定一套统一的编码规范和风格,并确保所有开发人员都能够按照这套规范进行编码。可以使用 shellcheck 等工具来检查代码是否符合规范。
5.2 高效率编程技巧
5.2.1 利用现有工具
在编写 Bash 脚本时,可以利用现有的工具或库来提高程序的效率和可靠性。例如,可以使用 curl 命令从网络上获取数据,使用 jq 命令对 JSON 数据进行处理,使用 sed 和 awk 命令对文本进行处理等等。
5.2.2 代码复用与优化
为了提高代码的复用性和效率,可以将常用的功能封装成函数或模块,并将这些函数或模块放在库文件中,在需要的时候进行导入使用。同时,还可以优化程序性能,例如避免不必要的循环、缓存数据等等。
5.3 安全性与稳定性
5.3.1 权限管理
在编写 Bash 脚本时,应该充分考虑脚本的安全性和稳定性。为了保护系统和数据的安全,应该严格控制脚本的执行权限,避免给予过高的权限。同时,还应该对输入参数进行校验和过滤,以避免注入攻击等安全问题。
5.3.2 错误处理与日志记录
为了保证程序的稳定性,应该编写健壮的错误处理代码,并对错误进行适当的处理或记录。可以将错误信息输出到终端或者记录到日志文件中,以便于调试和分析问题。同时,还应该在脚本中添加适当的检查点,以避免程序意外崩溃或死锁。
六、实战案例与总结
6.1 实战案例分析
6.1.1 自动化部署Web项目脚本
#!/bin/bash
# 定义变量
project_name="my-project"
git_repo="https://github.com/username/my-project.git"
project_dir="/var/www/html/my-project"
# 检查目录是否存在
if [ -d "$project_dir" ]; then
echo "Project directory already exists. Removing..."
rm -rf $project_dir
# 克隆代码
echo "Cloning project from Git repo..."
git clone $git_repo $project_dir
# 切换到项目目录
cd $project_dir || exit
# 安装依赖
echo "Installing dependencies..."
npm install
# 构建代码
echo "Building project..."
npm run build
# 启动项目
echo "Starting project..."
pm2 start server.js --name $project_name
# 配置 Nginx 反向代理
echo "Configuring Nginx..."
sudo tee /etc/nginx/sites-available/$project_name <<EOF
server {
listen 80;
server_name test.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host \$host;
proxy_cache_bypass \$http_upgrade;
# 检查 Nginx 配置是否正确
echo "Checking Nginx configuration..."
if sudo nginx -t; then
# 如果配置无误,启用配置并重启 Nginx
sudo ln -s /etc/nginx/sites-available/$project_name /etc/nginx/sites-enabled/
sudo systemctl restart nginx
echo "Deployment complete!"
# 如果配置有误,恢复原有状态
sudo rm /etc/nginx/sites-available/$project_name
rm -rf $project_dir
echo "Nginx configuration is invalid. Deployment failed."
上面这是一个 Bash 脚本,用于自动化部署一个 Node.js 项目。脚本假设已经在服务器上安装了 Git、Node.js、npm、pm2 和 Nginx 等必要的工具和服务。
该脚本执行以下步骤:
- 定义了一些变量,包括项目名称、Git 仓库地址、项目路径等。
- 检查项目目录是否存在,如果存在则删除。
- 克隆代码到指定目录。
- 进入项目目录,安装依赖。
- 构建项目代码。
- 启动项目。
- 配置 Nginx 反向代理。
- 检查 Nginx 配置是否正确,如果正确,则启用配置并重启 Nginx;否则,恢复原有状态并输出错误信息。
6.1.2 自动化部署Docker项目脚本
#!/bin/bash
# 定义变量
project_name="my-project"
docker_repo="username/my-project"
docker_tag="latest"
docker_network="my-network"
data_volume="$PWD/data:/app/data"
log_volume="$PWD/logs:/var/log/nginx"
# 检查容器是否存在
if [ "$(docker ps -q -f name=$project_name)" ]; then
echo "Container already exists. Stopping and removing..."
docker stop $project_name && docker rm $project_name
# 创建 Docker 网络
if ! $(docker network ls | grep -q $docker_network); then
echo "Network not found. Creating..."
docker network create $docker_network
# 拉取 Docker 镜像
echo "Pulling Docker image..."
docker pull $docker_repo:$docker_tag
# 启动 Docker 容器
echo "Starting Docker container..."
docker run \
--name $project_name \
--network $docker_network \
-v $data_volume \
-v $log_volume \
-p 80:80 \
-d $docker_repo:$docker_tag
# 检查容器是否成功启动
echo "Checking container status..."
if [ "$(docker ps -q -f name=$project_name -f status=running)" ]; then
echo "Deployment complete!"
# 如果容器启动失败,则删除容器和网络,并输出错误信息
docker stop $project_name && docker rm $project_name
docker network rm $docker_network
echo "Failed to start container. Deployment failed."
fi
是一个 Bash 脚本,用于自动化部署 Docker 项目。该脚本会执行以下步骤:
- 定义一些变量,包括项目名称、Docker 镜像仓库地址、标签等。
- 检查容器是否已经存在,如果存在则先停止并删除容器。
- 创建 Docker 网络(如果尚未创建),用于与其他容器通信。
- 从 Docker 仓库中拉取指定的镜像。
- 启动 Docker 容器,并挂载数据卷和日志卷,并将容器端口映射到主机端口上。
- 检查容器是否成功启动。
以上脚本还包含了在容器启动失败时的处理逻辑,即删除容器和网络,并输出错误信息。
需要注意的是,在使用该脚本前,需要确保系统已经安装 Docker 并具备相关管理权限。
6.1.3 系统监控与报警
#!/bin/bash
# 定义变量
cpu_threshold=80
mem_threshold=80
email_recipient="admin@example.com"
email_subject="System Alert"
# 获取 CPU 使用率和内存使用率
cpu_usage=$(top -b -n1 | grep "Cpu(s)" | awk '{print $2}')
mem_usage=$(free | awk '/Mem/{ printf("%d\n"), $3/$2*100 }')
# 判断 CPU 和内存使用率是否超过阈值
if [ "$cpu_usage" -gt "$cpu_threshold" ] || [ "$mem_usage" -gt "$mem_threshold" ]; then
# 如果超过阈值,则发送邮件告警
email_body="CPU usage: $cpu_usage%, Mem usage: $mem_usage%"
sendmail -t <<EOF
From: "System Monitoring" <no-reply@example.com>
To: $email_recipient
Subject: $email_subject
$email_body
fi
以上脚本会在定时任务中运行,每隔一段时间获取当前系统的 CPU 使用率和内存使用率,并将它们与预设的阈值进行比较。如果超过阈值,则通过邮件等方式发出告警信息。
6.1.4 shell写一个Linux管理系统
#!/bin/bash
# 判断系统类型,选择合适的包管理器
if [ -n "$(command -v yum)" ]; then
PKGMGR="yum"
elif [ -n "$(command -v apt-get)" ]; then
PKGMGR="apt-get"
echo "无法确认系统类型,请手动安装软件包。"
exit 1
# 安装必需的工具和软件包
for TOOL in curl tar zstd unzip; do
if ! command -v $TOOL > /dev/null; then
sudo $PKGMGR install -y $TOOL
# 菜单文字提示
function menu() {
cat << EOF
=========================================
Linux 系统管理工具
=========================================
1. 进程管理
2. 磁盘管理
3. 网络管理
4. 日志分析
5. 用户管理
6. 安全管理
7. 系统信息
8. 定时任务
0. 退出
=========================================
read -p "请输入数字选择相应的菜单:" CHOICE
# 进程管理
function process_mgmt() {
while true
cat << EOF
-----------------------------------------
-----------------------------------------
1. 列出所有进程
2. 杀死指定进程
3. 按照端口杀死进程
0. 返回上一级菜单
-----------------------------------------
read -p "请输入数字选择相应的菜单:" CHOICE
case $CHOICE in
ps aux
read -p "请输入要杀死的进程 ID:" PID
kill $PID
read -p "请输入要杀死的端口号:" PORT
sudo fuser -k $PORT/tcp
break
echo "错误的选择。"
# 磁盘管理
function disk_mgmt() {
while true
cat << EOF
-----------------------------------------
-----------------------------------------
1. 查看磁盘使用情况
2. 清理磁盘空间
0. 返回上一级菜单
-----------------------------------------
read -p "请输入数字选择相应的菜单:" CHOICE
case $CHOICE in
df -h
read -p "请输入要清理的文件路径:" PATH
sudo find $PATH -type f -mtime +30 -delete
break
echo "错误的选择。"
# 网络管理
function network_mgmt() {
while true
cat << EOF
-----------------------------------------
-----------------------------------------
1. 查看网络连接
2. 配置网络接口
3. 查询端口信息
4. 扫描局域网设备
0. 返回上一级菜单
-----------------------------------------
read -p "请输入数字选择相应的菜单:" CHOICE
case $CHOICE in
netstat -anp
sudo nano /etc/network/interfaces
read -p "请输入要查询的端口号:" PORT
sudo lsof -i:$PORT
read -p "请输入 IP 地址范围(例如:192.168.1.1/24):" IP_RANGE
sudo nmap -sP $IP_RANGE
break
echo "错误的选择。"
# 日志分析
function log_analysis() {
while true
cat << EOF
-----------------------------------------
-----------------------------------------
1. 查看系统日志
2. 筛选关键字
3. 保存日志
0. 返回上一级菜单
-----------------------------------------
read -p "请输入数字选择相应的菜单:" CHOICE
case $CHOICE in
cat /var/log/syslog
read -p "请输入要筛选的关键字:" KEYWORD
cat /var/log/syslog | grep $KEYWORD
read -p "请输入要保存的文件路径:" FILEPATH
cat /var/log/syslog > $FILEPATH
break
echo "错误的选择。"
# 用户管理
function user_mgmt() {
while true
cat << EOF
-----------------------------------------
-----------------------------------------
1. 查看用户列表
2. 添加用户
3. 删除用户
4. 修改用户密码
0. 返回上一级菜单
-----------------------------------------
read -p "请输入数字选择相应的菜单:" CHOICE
case $CHOICE in
cat /etc/passwd
read -p "请输入新用户的用户名:" USERNAME
sudo adduser $USERNAME
read -p "请输入要删除的用户的用户名:" USERNAME
sudo userdel -r $USERNAME
read -p "请输入要修改密码的用户名:" USERNAME
sudo passwd $USERNAME
break
echo "错误的选择。"
# 安全管理
function security_mgmt() {
while true
cat << EOF
-----------------------------------------
-----------------------------------------
1. 修改 SSH 端口
2. 禁止 ROOT 登录
0. 返回上一级菜单
-----------------------------------------
read -p "请输入数字选择相应的菜单:" CHOICE
case $CHOICE in
read -p "请输入新的 SSH 端口号:" PORT
sudo sed -i "s/Port .*/Port $PORT/g" /etc/ssh/sshd_config
sudo service sshd restart
sudo sed -i "s/PermitRootLogin yes/PermitRootLogin no/g" /etc/ssh/sshd_config
sudo service sshd restart
break
echo "错误的选择。"
# 系统信息
function system_info() {
cat << EOF
=========================================
=========================================
操作系统:$(lsb_release -d | cut -f2-)
内核版本:$(uname -r)
CPU 信息:$(grep "model name" /proc/cpuinfo | head -n1 | cut -d: -f2-)
内存信息:$(free -h | awk 'NR==2 {print $2}')
磁盘信息:$(df -h | awk '$NF=="/" {print "总容量:" $2 ", 剩余容量:" $4}')
=========================================
# 定时任务
function cron_job() {
crontab -l
# 主循环
while true
case $CHOICE in
process_mgmt
disk_mgmt
network_mgmt
log_analysis
user_mgmt
security_mgmt
system_info
cron_job
echo "谢谢使用,再见!"
exit 0
echo "错误的选择。"
6.1.5 shell写一个Docker管理系统
#!/bin/bash
# 判断操作系统类型
OS_TYPE=$(awk -F= '/^NAME/{print $2}' /etc/os-release)
# 输出菜单
function show_menu() {
echo "========================================="
echo " Docker 管理脚本"
echo "========================================="
echo " 1. 查询 Docker 版本"
echo " 2. 查询 Docker 状态"
echo " 3. 开启 Docker"
echo " 4. 关闭 Docker"
echo " 5. 重启 Docker"
echo " 6. 查询镜像列表"
echo " 7. 拉取镜像或重新拉取镜像"
echo " 8. 删除镜像"
echo " 9. 执行容器命令"
echo " 10. 显示所有容器信息"
echo " 11. 删除所有容器"
echo " 12. 退出"
echo "========================================="
# 检查用户输入是否合法
function check_input() {
while true; do
read -p "请输入您的选择(输入数字):" choice
case $choice in
[1-9]|10|11|12)
break
echo "无效的选择,请重新输入!"
# 检查 Docker 状态
function check_docker_status() {
systemctl status docker | grep "Active: active (running)" &> /dev/null
if [ $? -eq 0 ]; then
echo "Docker 正在运行!"
return 0
echo "Docker 已停止运行!"
return 1
# 启动 Docker
function start_docker() {
systemctl start docker
if [ $? -eq 0 ]; then
echo "Docker 启动成功!"
return 0
echo "Docker 启动失败!"
return 1
# 停止 Docker
function stop_docker() {
systemctl stop docker
if [ $? -eq 0 ]; then
echo "Docker 停止成功!"
return 0
echo "Docker 停止失败!"
return 1
# 重启 Docker
function restart_docker() {
systemctl restart docker
if [ $? -eq 0 ]; then
echo "Docker 重启成功!"
return 0
echo "Docker 重启失败!"
return 1
# 查询 Docker 版本
function check_docker_version() {
docker version &> /dev/null
if [ $? -eq 0 ]; then
echo "当前 Docker 版本为:"
docker version | grep Version
return 0
echo "查询 Docker 版本失败!"
return 1
# 查询镜像列表
function list_images() {
docker images
# 拉取镜像或重新拉取镜像
function pull_image() {
read -p "请输入要拉取的镜像名称(如ubuntu):" image_name
read -p "请输入要拉取的镜像版本(如18.04):" image_version
sudo docker pull $image_name:$image_version
if [ $? -eq 0 ]; then
echo "镜像 $image_name:$image_version 拉取成功!"
return 0
echo "镜像 $image_name:$image_version 拉取失败!"
return 1
# 删除指定的镜像
function delete_image() {
read -p "请输入要删除的镜像名称和版本(如ubuntu:18.04):" image_tag
sudo docker rmi $image_tag
if [ $? -eq 0 ]; then
echo "镜像 $image_tag 删除成功!"
return 0
echo "镜像 $image_tag 删除失败!"
return 1
# 执行容器命令
function exec_container() {
echo "请选择一个容器:"
docker ps -a
while true; do
read -p "请输入容器 ID:" container_id
docker ps -a --filter "id=$container_id" &> /dev/null
if [ $? -eq 0 ]; then
break
echo "无效的容器 ID,请重新输入!"
echo "请输入要执行的命令:"
read -e command
docker exec -it $container_id $command
# 显示所有容器信息
function show_containers() {
docker ps -a
# 删除所有停止运行的容器
function delete_containers() {
docker ps -a --filter "status=exited" --format "{{.ID}}" | xargs -r docker rm
echo "所有已停止的容器已删除!"
# 主函数
function main() {
while true; do
show_menu
check_input
case $choice in
check_docker_version
check_docker_status
if check_docker_status; then
echo "Docker 已经在运行,无需重复启动!"
start_docker
if check_docker_status; then
stop_docker
echo "Docker 已经停止,无需重复关闭!"
if check_docker_status; then
restart_docker
echo "Docker 已经停止,无法执行重启操作!"
list_images
pull_image
delete_image
exec_container
show_containers
delete_containers
exit 0
echo "无效的选择,请重新输入!"
read -n1 -r -p $'按任意键返回菜单...\n' key
# 检查操作系统类型是否支持
if [[ "$OS_TYPE" =~ "Ubuntu" ]] || [[ "$OS_TYPE" =~ "CentOS" ]]; then
echo "不支持的操作系统类型!"
fi
6.1.6 shell写一个自动化构建Docker镜像脚本
#!/bin/bash
# 检查 Docker 是否已安装
if ! [ -x "$(command -v docker)" ]; then
echo '错误:Docker 未安装,请先安装 Docker!' >&2
exit 1
# 检查 Docker 是否正在运行
if ! systemctl is-active docker > /dev/null; then
echo '错误:Docker 已停止,请先启动 Docker!' >&2
exit 1
# 检查脚本是否在 JAR 包所在目录下运行
CURRENT_DIR=$(pwd)
if [ $(ls *.jar 2>/dev/null | wc -l) -eq 0 ]; then
echo "错误:当前目录下没有 JAR 包,请将 JAR 包放入该目录再运行此脚本!" >&2
exit 1
# ---- 用户自定义变量 ----
read -p "请输入项目名称:" PROJECT_NAME
JARS=($(ls *.jar))
# 列出当前目录下的所有 JAR 包供用户选择
if [ ${#JARS[@]} -eq 0 ]; then
echo "错误:当前目录下没有 JAR 包,请将 JAR 包放入该目录再运行此脚本!" >&2
exit 1
echo "请选择 JAR 包(输入对应的编号):"
for i in "${!JARS[@]}"; do
echo "$((i+1)). ${JARS[$i]}"
read -p "请输入选择的编号(默认为1):" JAR_INDEX
JAR_INDEX=${JAR_INDEX:-"1"}
JAR_FILE=${JARS[$((JAR_INDEX-1))]}
read -p "请输入镜像名称(默认为 ${PROJECT_NAME}):" IMAGE_NAME
read -p "请输入初始镜像版本号(默认为 1.0.0):" IMAGE_VER
read -p "请输入暴露端口号(默认为 8080):" EXPOSE_PORT
read -p "请输入维护者信息(示例:Your Name <your.email@example.com>):" MAINTAINER
# 处理用户输入
IMAGE_NAME=${IMAGE_NAME:-"${PROJECT_NAME}"}
IMAGE_VER=${IMAGE_VER:-"1.0.0"}
EXPOSE_PORT=${EXPOSE_PORT:-"8080"}
MAINTAINER=${MAINTAINER:-"Your Name <your.email@example.com>"}
# 新建 Dockerfile 子目录
DOCKERFILE_DIR=dockerfile
if [ ! -d "$DOCKERFILE_DIR" ]; then
echo "正在创建目录 $DOCKERFILE_DIR..."
mkdir -p "$DOCKERFILE_DIR"
# 根据版本号递增生成镜像标签
if docker images "${IMAGE_NAME}:${IMAGE_VER}" &> /dev/null; then
echo "镜像 ${IMAGE_NAME}:${IMAGE_VER} 已存在,自动递增版本号..."
i=0
while docker images "${IMAGE_NAME}:${IMAGE_VER}-$((i+1))" &> /dev/null; do
let i++
IMAGE_TAG="${IMAGE_VER}-$((i+1))"
IMAGE_TAG="${IMAGE_VER}"
# 自动生成 Dockerfile 文件
DOCKERFILE_PATH="${DOCKERFILE_DIR}/${IMAGE_NAME}-${IMAGE_TAG//./_}.Dockerfile"
DOCKERFILE=$(cat << EOF
FROM openjdk:8-jre-alpine
LABEL maintainer="${MAINTAINER}"
COPY ${JAR_FILE} /app/${PROJECT_NAME}.jar
EXPOSE ${EXPOSE_PORT}
CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app/${PROJECT_NAME}.jar"]
echo "$DOCKERFILE" > "$DOCKERFILE_PATH"
# 构建 Docker 镜像
docker build -t "${IMAGE_NAME}:${IMAGE_TAG}" -f "$DOCKERFILE_PATH" .
if [ $? -eq 0 ]; then
echo "Docker 镜像构建成功!"
echo "镜像名称:${IMAGE_NAME}:${IMAGE_TAG}"
echo "Docker 镜像构建失败!"
这个脚本用于自动化构建 Docker 镜像,其中包括以下步骤:
- 检查 Docker 是否已安装,并且是否正在运行。
- 检查脚本是否在 JAR 包所在目录下运行,并列出当前目录下的所有 JAR 包供用户选择。
- 根据用户输入的信息,生成 Dockerfile 文件并自动构建 Docker 镜像。
具体来说,这个脚本首先使用
command -v
命令检查 Docker 是否已经安装,并通过
systemctl is-active
命令检查 Docker 是否正在运行。如果 Docker 未安装或停止运行,则会输出错误提示并退出脚本。
然后,脚本会检查是否有 JAR 包存在,并列出可用的 JAR 包供用户选择。用户可以根据输出结果输入相应的编号,选择需要构建 Docker 镜像的 JAR 包。脚本还会要求用户输入一些必要的信息,例如镜像名称、版本号、暴露端口等。
接着,脚本会根据用户输入的信息,生成 Dockerfile 文件并自动构建 Docker 镜像。Dockerfile 文件是根据用户输入的信息和模板内容自动生成的,其中包含了从官方的 OpenJDK 8 运行时镜像中获取 JRE,将 JAR 包复制到容器中,设置暴露端口等指令。脚本还会根据版本号递增生成镜像标签,以避免重复命名的冲突。
最后,脚本会输出构建结果,并显示构建成功的 Docker 镜像名称和版本号等信息。
6.1.7 shell写一个定时执行python脚本的脚本
#!/bin/bash
# 设置 Python 脚本文件路径和执行频率
PYTHON_SCRIPT="/path/to/script.py"
CRON_SCHEDULE="0 0 * * *"