一站式Shell编程攻略:从入门到精通

一站式Shell编程攻略:从入门到精通

一、Shell编程简介

1.1 Shell的定义与功能

Shell是一种命令行解释器,是在计算机操作系统中提供用户与操作系统交互的一种方式。通常Shell是指命令行界面,用户通过Shell界面可以输入命令并获得相应的操作结果。

Shell的主要功能包括:

  1. 解释和执行用户输入的命令:用户可以通过Shell界面输入各种命令,Shell会将这些命令解释并执行相应的操作。例如,用户可以输入ls命令来查看当前目录下的文件列表。
  2. 管理和控制进程:Shell可以启动、停止、暂停和重启进程,还可以查看和管理当前正在运行的进程。例如,用户可以通过Shell启动一个后台进程,或者通过Shell杀死一个卡死的进程。
  3. 文件和目录管理:Shell可以对文件和目录进行各种操作,如创建、删除、复制、移动、重命名等等。用户可以通过Shell在文件系统中进行各种操作。
  4. 系统管理:Shell还可以管理和配置系统设置、环境变量、网络配置等等。例如,用户可以通过Shell配置网络连接,修改系统环境变量等等。

1.1.1 Shell的作用

Shell的主要作用有以下几个方面:

  1. 提供命令行界面:Shell提供了一个命令行界面,用户可以通过键盘输入命令来与操作系统进行交互。这种交互方式相对于图形用户界面更加高效,可以让用户快速地完成各种操作。
  2. 管理文件和目录:Shell可以对文件和目录进行各种操作,如创建、删除、复制、移动、重命名等等。用户可以通过Shell在文件系统中进行各种操作,例如创建文件夹、查看文件内容、修改文件权限等。
  3. 执行各种命令和程序:用户可以通过Shell执行各种命令和程序,如编译代码、运行脚本、启动服务等。Shell会将用户输入的命令解释并执行相应的操作。
  4. 管理进程和系统资源:Shell可以管理和控制进程,包括启动、停止、暂停和重启进程,还可以查看和管理当前正在运行的进程。同时,Shell还可以管理系统资源,如内存、CPU等。
  5. 配置系统和环境:Shell可以管理和配置系统设置、环境变量、网络配置等等。用户可以通过Shell配置网络连接,修改系统环境变量等等。

1.1.2 常见的Shell类型

  1. Bourne Shell(sh):Bourne Shell是Unix操作系统中最早的Shell,由Stephen Bourne开发。它是大多数Unix系统中默认的Shell,也是其他Shell的基础。Bourne Shell是一种比较简单的Shell,常用于编写Shell脚本和自动化任务。
  2. C Shell(csh):C Shell由Bill Joy开发,是一种比较高级的Shell。它具有C语言风格的语法和交互式命令历史功能,可以方便地编写复杂的Shell脚本和交互式应用程序。C Shell通常用于编写交互式应用程序和系统管理任务。
  3. Korn Shell(ksh):Korn Shell是由AT&T Bell实验室的David Korn开发的一种Shell,它是Bourne Shell的升级版,具有更加强大的编程功能。Korn Shell支持数组、函数、变量替换和命令行编辑等高级功能,也是Shell脚本编程中常用的一种Shell。
  4. 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 等必要的工具和服务。

该脚本执行以下步骤:

  1. 定义了一些变量,包括项目名称、Git 仓库地址、项目路径等。
  2. 检查项目目录是否存在,如果存在则删除。
  3. 克隆代码到指定目录。
  4. 进入项目目录,安装依赖。
  5. 构建项目代码。
  6. 启动项目。
  7. 配置 Nginx 反向代理。
  8. 检查 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 项目。该脚本会执行以下步骤:

  1. 定义一些变量,包括项目名称、Docker 镜像仓库地址、标签等。
  2. 检查容器是否已经存在,如果存在则先停止并删除容器。
  3. 创建 Docker 网络(如果尚未创建),用于与其他容器通信。
  4. 从 Docker 仓库中拉取指定的镜像。
  5. 启动 Docker 容器,并挂载数据卷和日志卷,并将容器端口映射到主机端口上。
  6. 检查容器是否成功启动。

以上脚本还包含了在容器启动失败时的处理逻辑,即删除容器和网络,并输出错误信息。

需要注意的是,在使用该脚本前,需要确保系统已经安装 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 镜像,其中包括以下步骤:

  1. 检查 Docker 是否已安装,并且是否正在运行。
  2. 检查脚本是否在 JAR 包所在目录下运行,并列出当前目录下的所有 JAR 包供用户选择。
  3. 根据用户输入的信息,生成 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 * * *"