最新资讯

  • linux入门六:Linux Shell 编程

linux入门六:Linux Shell 编程

2025-04-29 15:00:06 0 阅读

一、Shell 概述

1. 什么是 Shell?

Shell 是 Linux 系统中用户与内核之间的桥梁,作为 命令解析器,它负责将用户输入的文本命令转换为计算机可执行的机器指令。

  • 本质:Shell 是一个程序(如常见的 Bash、Zsh),而 Shell 脚本则是包含一系列命令的文本文件,通常以 .sh 结尾(非强制,仅为识别方便)。
  • 作用:批量执行重复命令、实现自动化任务、编写复杂逻辑程序。

2. 为什么选择 Bash?

  • 主流性:Bash(Bourne Again Shell)是 Linux 系统的默认 Shell,几乎所有发行版都内置,兼容性强。
  • 功能强大:支持变量、数组、函数、流程控制等高级特性,满足从简单脚本到复杂程序的需求。
  • 学习门槛低:语法简洁,对新手友好,且与早期 Shell(如 Bourne Shell)兼容。

二、Shell 脚本基础操作

1. 脚本文件的创建与编辑

1.1 选择文本编辑器

Shell 脚本本质是纯文本文件,推荐使用以下编辑器:

  • nano(新手友好):命令行下的简单编辑器,通过 nano 文件名 启动,支持鼠标和快捷键操作。
  • vim(功能强大):通过 vim 文件名 启动,需切换模式(i 进入插入模式,Esc 退出,:wq 保存并退出)。
  • gedit(图形界面):适合桌面环境,直接右键文件选择「用文本编辑器打开」。
1.2 创建脚本文件
# 在当前目录创建名为 demo.sh 的脚本文件
touch demo.sh
1.3 编写脚本内容
# 用 nano 打开并编辑脚本
nano demo.sh

输入以下内容:

#!/bin/bash
# 这是一个简单的 Shell 脚本示例
echo "Hello, World!"  # 输出文本

关键行解释

  • #!/bin/bash:指定脚本使用 Bash 解释器执行,必须位于文件第一行。
  • # 开头的行是注释,用于解释代码逻辑,不参与执行。
  • echo 命令用于输出文本,默认换行。若需不换行,使用 echo -n "内容"

2. 脚本的执行方式

2.1 方式一:通过 bash 命令执行(无需权限)
bash demo.sh

原理:直接调用 Bash 解释器执行脚本,适用于快速测试,无需修改文件权限。

2.2 方式二:通过 sh 命令执行(兼容旧版)
sh demo.sh

注意sh 通常指向 Bash,但某些系统中可能指向更古老的 Shell(如 BusyBox sh),可能导致兼容性问题。建议统一使用 #!/bin/bash 头部。

2.3 方式三:赋予执行权限后运行(推荐)
# 赋予文件执行权限
chmod +x demo.sh
# 通过相对路径执行
./demo.sh

关键点

  • chmod +x 用于添加执行权限,否则会提示 Permission denied
  • ./ 表示当前目录,必须显式指定路径,因为当前目录默认不在系统 PATH 中。

3. 脚本执行的常见问题与解决

3.1 权限不足

错误提示Permission denied
解决方法

chmod +x demo.sh  # 赋予执行权限
3.2 路径错误

错误提示No such file or directory
可能原因

  1. 脚本路径错误(如 ./demo.sh 写成 demo.sh)。
  2. 脚本文件格式问题(如 Windows 换行符导致的错误)。
    解决方法
# 检查路径是否正确
ls -l demo.sh  # 确认文件存在且路径正确

# 转换文件格式为 Unix 格式(若文件来自 Windows)
dos2unix demo.sh  # 需先安装 dos2unix 工具
3.3 解释器路径错误

错误提示Bad interpreter: No such file or directory
可能原因:脚本头部 #!/bin/bash 路径错误。
解决方法

# 查看系统 Bash 路径
which bash  # 通常输出 /bin/bash

# 修改脚本头部为正确路径
vim demo.sh  # 将第一行改为 #!/usr/bin/env bash(更具可移植性)

4. 脚本调试与验证

4.1 检查执行结果
# 执行脚本并查看输出
./demo.sh  # 正常输出:Hello, World!

# 检查命令执行状态(0 表示成功)
echo $?  # 输出:0
4.2 调试模式
# 启用调试模式,显示每行执行的命令
bash -x demo.sh
4.3 错误处理
# 脚本遇到错误时立即退出
set -e

# 捕获错误并输出信息
trap 'echo "错误发生在第 $LINENO 行"' ERR

5. 脚本优化与进阶

5.1 输出重定向
# 将输出保存到文件(覆盖原有内容)
./demo.sh > output.log

# 追加输出到文件
./demo.sh >> output.log
5.2 输入重定向
# 从文件读取输入
cat input.txt | ./demo.sh
5.3 环境变量与脚本交互
# 在脚本中引用环境变量
echo "当前用户:$USER,主目录:$HOME"

# 导出自定义变量到子进程
export MY_VAR="自定义变量"

6. 实战案例:批量创建用户

#!/bin/bash
# 批量创建用户脚本

# 定义用户列表
users=("user1" "user2" "user3")

# 遍历用户列表并创建用户
for user in ${users[@]}; do
  useradd $user && echo "用户 $user 创建成功" || echo "用户 $user 创建失败"
done

执行步骤

  1. 保存脚本为 create_users.sh
  2. 赋予执行权限:chmod +x create_users.sh
  3. 执行脚本:./create_users.sh

7. 常见易错点总结

  1. 变量赋值空格a = 10 错误,必须为 a=10
  2. 中括号空格[条件] 需写成 [ 条件 ](如 [ $a -gt 5 ])。
  3. 路径问题:执行脚本需用 ./脚本名,直接输入 脚本名 会提示 “命令未找到”。
  4. 转义符遗漏:使用 expr 计算乘法时,* 需转义为 *(如 expr 5 * 3)。
  5. 文件格式错误:Windows 格式文件需转换为 Unix 格式(使用 dos2unix)。

8. 拓展知识

8.1 脚本可移植性
  • 推荐头部#!/usr/bin/env bash,使用 env 命令自动查找 Bash 路径,避免硬编码。
  • 兼容性检查:使用 sh 命令测试脚本在旧版 Shell 中的运行情况。
8.2 权限设置最佳实践
  • 最小权限原则:仅赋予脚本所有者执行权限(chmod u+x 脚本名)。
  • 特殊权限setuidchmod u+s 脚本名)允许普通用户以脚本所有者权限执行。
8.3 脚本性能优化
  • 使用内置命令:优先使用 Bash 内置命令(如 echocd),避免调用外部程序。
  • 减少 I/O 操作:将多次 echo 合并为一次输出,或使用 printf 提升效率。

通过以上步骤,你可以全面掌握 Shell 脚本的基础操作,从创建、编辑到执行、调试,再到优化和实战应用。建议结合实际案例反复练习,加深对脚本执行原理的理解。

三、变量:脚本的 “数据细胞”

1. 变量基础:从存储到操作

1.1 变量定义与引用

定义变量

name="Alice"          # 字符串变量(值含空格需用引号包裹)
age=25                # 数值变量(本质为字符串,可参与计算)
file_path="/etc/passwd"  # 路径变量

关键规则

  • 变量名必须以字母或下划线开头,区分大小写(如 Name 和 name 是不同变量)。
  • 等号两边不能有空格(name = "Alice" 会报错)。

引用变量

echo "姓名:$name,年龄:${age}岁"
# 输出:姓名:Alice,年龄:25岁

推荐写法:使用 ${变量名} 避免歧义,例如:

fruit="apple"
echo "${fruit}s"  # 输出:apples(正确)
echo "$fruits"    # 输出:(错误,变量名歧义)
1.2 单引号 vs 双引号
符号特性示例
''原样输出,不解析变量和转义符echo '$name' → $name
""解析变量和转义符(如   换行)echo "$name " → Alice 换行

实战场景

msg='当前用户:$USER,主目录:$HOME'
echo $msg  # 输出:当前用户:$USER,主目录:$HOME

msg="当前用户:$USER,主目录:$HOME"
echo $msg  # 输出:当前用户:root,主目录:/root

2. 数值计算:从基础到高级

2.1 算术运算符
运算符示例(a=10b=3结果
+$((a + b))13
-$((a - b))7
*$((a * b))30
/$((a / b))3
%$((a % b))1

推荐方法

# 方法 1:$(( ))(简洁高效)
sum=$((5 + 3))          # 8
product=$((5 * 3))      # 15

# 方法 2:expr(需转义乘号)
sum=$(expr 5 + 3)       # 8
product=$(expr 5 * 3)  # 15(注意 `*`)
2.2 数值运算实战

案例:计算圆的面积

#!/bin/bash
radius=5
area=$((3.14 * radius * radius))  # 注意:整数运算会截断小数
echo "半径为 $radius 的圆面积:$area"  # 输出:78(实际应为 78.5)

改进方案

area=$(echo "3.14 * $radius * $radius" | bc)  # 使用 bc 工具支持浮点运算
echo "半径为 $radius 的圆面积:$area"  # 输出:78.5

3. 标准变量:系统级的数据仓库

3.1 常用环境变量
变量名含义示例(管理员用户)
$HOME用户主目录/root
$PWD当前工作目录/home/user/scripts
$USER当前用户名root
$PATH命令搜索路径:/usr/bin:/bin
$HOSTNAME主机名localhost.localdomain

实战示例

echo "当前用户:$USER,主目录:$HOME"
# 输出:当前用户:root,主目录:/root
3.2 永久设置环境变量
  1. 临时生效(当前终端有效):
    export MY_VAR="自定义变量"
    
  2. 永久生效(所有终端有效):
    # 编辑用户配置文件
    nano ~/.bashrc
    # 在文件末尾添加
    export MY_VAR="自定义变量"
    # 使配置生效
    source ~/.bashrc
    

4. 特殊变量:脚本参数与状态

4.1 位置参数
变量含义示例(脚本 test.sh 1 2 "a b"
$0脚本名称test.sh
$1~$9第 1 到第 9 个参数$1=1$2=2$3=a b
${10}第 10 个参数(需用大括号)$10=10(若参数足够)

示例脚本 args.sh

#!/bin/bash
echo "脚本名:$0"
echo "第一个参数:$1"
echo "第十个参数:${10}"

运行:

./args.sh 1 2 3 4 5 6 7 8 9 10
# 输出:
# 脚本名:./args.sh
# 第一个参数:1
# 第十个参数:10
4.2 其他特殊变量
变量含义示例(脚本 test.sh
$#参数个数3(若传递 3 个参数)
$@所有参数(独立字符串)1 2 "a b"
$*所有参数(单个字符串)1 2 a b(空格丢失)
$$脚本进程号(PID)12345(实际 PID)
$?上条命令退出状态(0 = 成功)0(若命令成功)

实战案例

#!/bin/bash
echo "参数个数:$#"
echo "所有参数($@):$@"
echo "所有参数($*):$*"

运行:

./test.sh hello "world!"
# 输出:
# 参数个数:2
# 所有参数($@):hello world!
# 所有参数($*):hello world!

5. 变量作用域:从全局到局部

5.1 全局变量

定义:在脚本任何位置定义的变量,默认在整个脚本有效。

#!/bin/bash
global_var="全局变量"

function show_var() {
  echo "函数内访问全局变量:$global_var"
}

show_var  # 输出:函数内访问全局变量:全局变量
echo "函数外访问全局变量:$global_var"  # 输出:函数外访问全局变量:全局变量
5.2 局部变量

定义:使用 local 关键字在函数内定义的变量,仅在函数内有效。

#!/bin/bash
function local_var_demo() {
  local local_var="局部变量"  # 仅函数内有效
  echo "函数内访问局部变量:$local_var"
}

local_var_demo  # 输出:函数内访问局部变量:局部变量
echo "函数外访问局部变量:$local_var"  # 输出:函数外访问局部变量:(空)

6. 高级变量操作:让脚本更灵活

6.1 变量替换
语法作用示例(str="hello world"
${str#h*o}从头部删除最短匹配 h*oworld
${str##h*o}从头部删除最长匹配 h*orld
${str%ld}从尾部删除最短匹配 ldhello wor
${str%%ld}从尾部删除最长匹配 ldhello wor
${str/world/Shell}替换第一个匹配项hello Shell
${str//l/LL}替换所有匹配项heLLo worLLd

实战案例

path="/home/user/documents/report.txt"
# 提取文件名
filename=${path##*/}  # 输出:report.txt
# 提取文件类型
extension=${filename##*.}  # 输出:txt
6.2 命令替换

语法

变量=$(命令)  # 推荐写法
变量=`命令`  # 反引号写法(易混淆)

示例

# 获取当前日期
date=$(date +%Y-%m-%d)
echo "今天日期:$date"  # 输出:今天日期:2023-10-01

# 获取文件行数
line_count=$(wc -l < /etc/passwd)
echo "用户文件行数:$line_count"  # 输出:用户文件行数:42

7. 常见易错点与解决方案

7.1 变量赋值空格错误

错误示例

name = "Alice"  # 报错:-bash: name: 未找到命令

解决方案

name="Alice"  # 正确写法
7.2 中括号条件判断空格缺失

错误示例

if [ $age -gt 18 ]; then  # 正确
if [ $age-gt 18 ]; then  # 错误(缺少空格)
7.3 数组定义逗号分隔

错误示例

names=("Kanye", "Edison", "Fish")  # 错误(逗号分隔)

解决方案

names=("Kanye" "Edison" "Fish")  # 正确(空格分隔)
7.4 变量命名冲突

错误示例

USER="自定义用户"  # 覆盖系统变量 $USER

解决方案

user="自定义用户"  # 使用小写字母避免冲突

8. 拓展知识:让变量更强大

8.1 只读变量
readonly PI=3.14  # 定义只读变量
PI=3.1415        # 报错:PI: 只读变量
8.2 删除变量
name="Alice"
unset name       # 删除变量
echo $name       # 输出:(空)
8.3 变量类型转换
num="123"
echo $((num + 100))  # 输出:223(自动转换为整数)

9. 实战案例:变量综合应用

9.1 批量重命名文件
#!/bin/bash
# 将当前目录下所有 .txt 文件重命名为 .log
for file in *.txt; do
  new_name="${file%.txt}.log"  # 替换扩展名
  mv "$file" "$new_name"
  echo "重命名:$file → $new_name"
done
9.2 动态获取系统信息
#!/bin/bash
# 获取系统负载、内存使用、用户数
load=$(uptime | awk -F 'load average:' '{print $2}' | cut -d ',' -f 1)
mem_used=$(free -h | awk '/Mem:/ {print $3}')
user_count=$(who | wc -l)

echo "系统负载:$load"
echo "内存使用:$mem_used"
echo "在线用户:$user_count"

10. 总结:变量的 “生存法则”

  • 命名规范:小写字母开头,避免与系统变量冲突。
  • 引号使用:值含空格或特殊字符时,优先使用双引号。
  • 作用域控制:函数内变量使用 local 声明,避免全局污染。
  • 性能优化:算术运算用 $(( )),命令替换用 $( )

通过以上内容,你将掌握 Shell 变量的核心操作,从基础定义到高级应用,再到实战案例,逐步提升脚本编写能力。变量是 Shell 编程的基石,熟练运用它们能让你的脚本更灵活、高效!

四、运算符与条件判断

1. 关系运算符(判断条件)

(1)数字比较
运算符含义示例(a=10b=20
-eq等于[ $a -eq $b ] → 假
-ne不等于[ $a -ne $b ] → 真
-gt大于[ $a -gt $b ] → 假
-lt小于[ $a -lt $b ] → 真
-ge大于等于[ $a -ge $b ] → 假
-le小于等于[ $a -le $b ] → 真
(2)字符串比较
运算符含义示例
-z字符串为空[ -z "" ] → 真
-n字符串非空[ -n "abc" ] → 真
==字符串相等[ "a" == "a" ] → 真
!=字符串不等[ "a" != "b" ] → 真
>字符串排序大于(需转义)[ "b" > "a" ] → 真
<字符串排序小于(需转义)[ "a" < "b" ] → 真
(3)文件判断
运算符含义示例
-e文件 / 目录存在[ -e /etc/passwd ] → 真
-f是普通文件[ -f first_script.sh ] → 真(若文件存在)
-d是目录[ -d /home ] → 真
-r文件可读[ -r /etc/shadow ] → 假(普通用户不可读)
-w文件可写[ -w first_script.sh ] → 真(若有写权限)
-x文件可执行[ -x first_script.sh ] → 真(若有执行权限)

2. 逻辑运算符(组合条件)

运算符含义示例
-a逻辑与(AND)[ $a -gt 5 -a $a -lt 15 ] → a 在 6-14 之间为真
-o逻辑或(OR)[ -f file -o -d dir ] → 文件或目录存在为真
!逻辑非(NOT)[ ! -e file ] → 文件不存在为真

注意

  • 条件判断需用中括号 [ ],且括号前后必须留空格(如 [ $a -gt 5 ],否则报错)。
  • 复杂条件可用 && 和 ||(适用于命令级逻辑,如 command1 && command2 表示 command1 成功后执行 command2)。

五、数组:批量数据处理

1. 定义数组

  • 方式 1:直接赋值(下标从 0 开始)
    fruits=("apple" "banana" "orange")  # 定义包含三个元素的数组
    
  • 方式 2:指定下标(支持稀疏数组)
    numbers[0]=10
    numbers[2]=30  # 下标 1 未定义,值为空
    
  • 方式 3:省略下标(自动递增)
    array=()
    array+=("one")  # 追加元素
    array+=("two")
    

2. 访问数组元素

  • 获取单个元素${数组名[下标]}
    echo ${fruits[1]}  # 输出:banana
    
  • 获取所有元素${数组名[@]} 或 ${数组名[*]}
    echo ${fruits[@]}  # 输出:apple banana orange
    
  • 获取数组长度${#数组名[@]}
    echo ${#fruits[@]}  # 输出:3
    
  • 切片操作(从下标 1 开始,取 2 个元素)
    echo ${fruits[@]:1:2}  # 输出:banana orange
    

3. 遍历数组示例

#!/bin/bash
nums=(1 3 5 7 9)
for num in ${nums[@]}; do  # 遍历数组所有元素
  echo "当前数字:$num"
done
# 输出:
# 当前数字:1
# 当前数字:3
# 当前数字:5
# 当前数字:7
# 当前数字:9

六、流程控制:脚本的 “逻辑大脑”

在 Shell 编程中,流程控制是实现复杂逻辑的核心。通过条件判断和循环结构,脚本可以根据不同场景执行不同操作,实现自动化任务。本节将从基础语法到实战案例,逐步解析 Shell 流程控制的核心知识点。

1. 条件判断:让脚本 “会思考”

1.1 if 语句:最基础的条件分支

语法格式

if [ 条件 ]; then
  命令1  # 条件为真时执行
elif [ 条件2 ]; then  # 可选,多个条件分支
  命令2
else  # 可选,所有条件不满足时执行
  命令3
fi  # 必须以 fi 结束

关键细节

  • 条件表达式:需用中括号 [ ] 包裹,且括号前后必须留空格(如 [ $a -gt 5 ],否则报错)。
  • 文件判断参数:常用 -e(存在)、-f(普通文件)、-d(目录)等(见下表)。
运算符含义示例
-e文件 / 目录存在[ -e /etc/passwd ] → 真
-f是普通文件[ -f script.sh ] → 真(若文件存在)
-d是目录[ -d /home ] → 真

示例:判断文件类型

#!/bin/bash
file="./test.txt"

if [ -e "$file" ]; then          # 文件存在
  if [ -f "$file" ]; then         # 是普通文件
    echo "文件 $file 是普通文件"
  elif [ -d "$file" ]; then       # 是目录
    echo "文件 $file 是目录"
  else                            # 其他类型(如链接、设备文件)
    echo "文件 $file 是特殊文件"
  fi
else
  echo "文件 $file 不存在"
fi
1.2 case 语句:模式匹配的高效选择

语法格式

case 变量 in
  模式1)
    命令1
    ;;  # 必须用双分号结束分支
  模式2)
    命令2
    ;;
  *)  # 通配符:匹配所有未定义的模式
    命令3
    ;;
esac  # 必须以 esac 结束

适用场景

  • 菜单驱动程序(如用户输入 1-5 选择操作)。
  • 文件类型判断(如根据扩展名执行不同解压命令)。

示例:简易菜单程序

#!/bin/bash
echo "请选择操作(1-3):"
echo "1. 查看当前目录"
echo "2. 查看系统时间"
echo "3. 退出程序"
read choice

case $choice in
  1)
    ls -l  # 列出当前目录文件
    ;;
  2)
    date +"%Y-%m-%d %H:%M:%S"  # 显示当前时间
    ;;
  3)
    echo "退出程序"
    exit 0  # 退出脚本
    ;;
  *)
    echo "无效选择!请输入 1-3"
    ;;
esac

2. 循环结构:让脚本 “重复执行”

2.1 for 循环:遍历列表或范围

格式 1:遍历列表(新手友好)

for 变量 in 元素1 元素2 元素3; do
  命令  # 对每个元素执行操作
done

示例:打印所有水果

fruits=("apple" "banana" "orange")
for fruit in ${fruits[@]}; do
  echo "当前水果:$fruit"
done
# 输出:
# 当前水果:apple
# 当前水果:banana
# 当前水果:orange

格式 2:C 语言风格(指定次数)

for ((初始值; 条件; 增量)); do
  命令  # 按次数循环
done

示例:计算 1+2+…+10

sum=0
for ((i=1; i<=10; i++)); do
  sum=$((sum + i))
done
echo "总和:$sum"  # 输出:55
2.2 while 循环:条件驱动的重复

语法格式

while [ 条件 ]; do
  命令  # 条件为真时持续执行
done

示例:逐行读取文件

#!/bin/bash
file="users.txt"
while read line; do  # 每次读取文件一行到变量 line
  echo "用户:$line"
done < "$file"  # 从文件获取输入(重定向)
2.3 until 循环:反条件循环

语法格式

until [ 条件 ]; do
  命令  # 条件为假时持续执行,直到条件为真
done

示例:等待文件生成

until [ -e "data.csv" ]; do  # 直到文件存在
  echo "等待 data.csv 生成..."
  sleep 1  # 休眠 1 秒
done
echo "文件已生成!"

3. 循环控制:让流程更灵活

3.1 break 与 continue
关键字作用示例
break跳出当前循环(类似 C 语言)for i in 1 2 3; do if [ $i -eq 2 ]; then break; fi; done(仅打印 1)
continue跳过当前循环迭代for i in 1 2 3; do if [ $i -eq 2 ]; then continue; fi; echo $i; done(打印 1, 3)
3.2 嵌套循环:解决复杂逻辑

示例:打印乘法表

for i in {1..9}; do
  for j in {1..9}; do
    echo -n "$i×$j=$((i*j)) "  # -n 不换行
  done
  echo  # 换行
done

4. 函数:代码复用的 “积木”

4.1 定义与调用函数

语法格式

# 格式 1(简洁写法)
函数名() {
  local 变量  # 声明局部变量(仅限函数内使用)
  命令       # 函数逻辑
  return 退出码  # 可选,0 表示成功,非 0 表示失败
}

# 格式 2(显式声明)
function 函数名() {
  命令
}

示例:计算两数之和

#!/bin/bash
# 定义函数:接收两个参数,返回和
add() {
  local a=$1  # 局部变量,避免污染全局作用域
  local b=$2
  echo $((a + b))  # 通过 echo 输出结果(推荐)
  return 0        # 返回成功状态
}

# 调用函数并获取结果
result=$(add 5 3)
echo "5 + 3 = $result"  # 输出:8
echo "函数返回值:$?"    # 输出:0(成功)
4.2 函数参数传递
  • 位置参数:函数内通过 $1$2 等获取调用时传递的参数。
  • 参数验证:调用前检查参数个数,避免空指针错误。
    add() {
      if [ $# -ne 2 ]; then  # 检查参数个数是否为 2
        echo "错误:需要 2 个参数"
        return 1
      fi
      # 逻辑代码
    }
    

5. 常见易错点与解决方案

5.1 中括号空格缺失

错误示例

if [ $age>18 ]; then  # 错误(缺少空格)
if [ $age -gt 18 ]; then  # 正确

解决方案:始终在中括号内外留空格([ 条件 ])。

5.2 case 分支遗漏 ;;

错误示例

case $choice in
  1) echo "选项 1"  # 缺少 ;;,导致语法错误
esac

解决方案:每个分支必须以 ;; 结束。

5.3 无限循环陷阱

错误示例

while [ 1 -eq 1 ]; do  # 条件永远为真,导致无限循环
  echo "陷阱!"
done

解决方案:确保循环条件最终会变为假,或用 break 强制退出。

6. 实战案例:流程控制综合应用

6.1 文件备份脚本
#!/bin/bash
# 功能:判断目录是否存在,存在则备份,否则创建并备份

backup_dir="/backup"
source_dir="/data"

# 判断备份目录是否存在
if [ ! -d "$backup_dir" ]; then
  mkdir -p "$backup_dir"  # 创建目录(-p 自动创建父目录)
  echo "创建备份目录:$backup_dir"
fi

# 备份数据(使用时间戳命名备份文件)
timestamp=$(date +%Y%m%d%H%M%S)
tar -czf "$backup_dir/data_$timestamp.tar.gz" "$source_dir"

echo "备份完成!文件路径:$backup_dir/data_$timestamp.tar.gz"
6.2 交互式猜数字游戏
#!/bin/bash
# 生成 1-100 随机数
num=$((RANDOM % 100 + 1))
attempts=0  # 记录尝试次数

while true; do  # 无限循环,直到猜对
  read -p "请输入一个数字(1-100):" guess
  attempts=$((attempts + 1))

  if [ $guess -eq $num ]; then
    echo "恭喜!你在 $attempts 次内猜对了!"
    break  # 跳出循环
  elif [ $guess -gt $num ]; then
    echo "猜大了!再试一次。"
  else
    echo "猜小了!再试一次。"
  fi
done

7. 拓展知识:让流程控制更强大

7.1 复合条件表达式
  • 逻辑与&&(如 command1 && command2,仅当 command1 成功时执行 command2)。
  • 逻辑或||(如 command1 || command2,仅当 command1 失败时执行 command2)。
7.2 函数递归

示例:计算阶乘(递归实现)

factorial() {
  local n=$1
  if [ $n -eq 0 ]; then
    echo 1
  else
    echo $((n * $(factorial $((n-1)))))
  fi
}

result=$(factorial 5)
echo "5 的阶乘:$result"  # 输出:120
7.3 循环性能优化
  • 减少 I/O:将多次 echo 合并为一次,或使用 printf 提升效率。
  • 避免全局变量:函数内使用 local 声明变量,提高代码可读性和安全性。

8. 总结:流程控制的 “黄金法则”

  1. 条件判断:善用 if 和 case,复杂逻辑用 case 提高可读性。
  2. 循环选择:列表遍历用 for,条件驱动用 while,反向条件用 until
  3. 函数设计:参数验证、局部变量、明确返回值,提升代码复用性。
  4. 调试技巧:用 set -x 开启调试模式,查看循环和条件的执行流程。

通过掌握流程控制,你将能编写具备 “智能” 的 Shell 脚本,实现从简单任务到复杂自动

七、函数:代码复用的核心

在 Shell 编程中,函数是实现代码复用和模块化的关键。通过将重复或通用的逻辑封装为函数,不仅能减少代码冗余,还能提高脚本的可读性和维护性。本节将从函数的基础语法出发,结合实战案例,逐步解析函数的核心知识点。

1. 函数基础:从定义到调用

1.1 函数定义的两种格式

格式 1:简洁写法(推荐新手)

函数名() {
  命令1
  命令2
  return 退出码  # 可选,默认返回最后一条命令的状态(0-255)
}

格式 2:显式声明(清晰易读)

function 函数名() {
  命令
}

关键说明

  • function 关键字可选,但显式声明能提高代码可读性。
  • return 用于指定退出码(0 表示成功,非 0 表示失败),省略时返回最后一条命令的状态。

示例:定义一个打招呼函数

greet() {
  echo "Hello, $1!"  # $1 是函数的第一个参数
  return 10  # 手动设置返回码为 10
}
1.2 调用函数与参数传递

语法

函数名 参数1 参数2 参数3  # 参数之间用空格分隔

示例:调用打招呼函数

greet "Alice"  # 输出:Hello, Alice!
echo "函数返回码:$?"  # 输出:10(通过 $? 获取返回码)

2. 参数处理:让函数更灵活

2.1 位置参数:函数的 “输入变量”
变量含义示例(函数调用 add 5 3
$1第一个参数5
$2第二个参数3
$#参数个数2
$@所有参数(独立字符串)5 3

示例:计算两数之和的函数

add() {
  local sum=$(( $1 + $2 ))  # local 声明局部变量,避免污染全局作用域
  echo "和为:$sum"  # 输出结果(推荐通过 echo 返回数据)
  return 0  # 返回成功状态码
}

# 调用函数并获取结果
result=$(add 5 3)  # 将函数输出赋值给变量
echo "计算结果:$result"  # 输出:计算结果:8
2.2 参数验证:避免无效输入

场景:当函数需要固定数量的参数时,先检查参数个数。

add() {
  if [ $# -ne 2 ]; then  # 检查参数是否为 2 个
    echo "错误:需要 2 个参数,实际 $# 个"
    return 1  # 返回错误码
  fi
  local sum=$(( $1 + $2 ))
  echo $sum
}

# 调用错误示例
add 5  # 输出:错误:需要 2 个参数,实际 1 个
echo "返回码:$?"  # 输出:1

3. 变量作用域:避免 “变量污染”

3.1 全局变量:脚本内处处可见

特点:在函数外定义的变量,或函数内未用 local 声明的变量,均可在全局访问。

global_var="全局变量"

show_global() {
  echo "函数内访问:$global_var"  # 可直接访问全局变量
}

show_global  # 输出:函数内访问:全局变量
echo "函数外访问:$global_var"  # 输出:函数外访问:全局变量
3.2 局部变量:函数内的 “私有数据”

语法:用 local 关键字声明,仅在函数内有效。

function local_demo() {
  local local_var="局部变量"  # 局部变量
  echo "函数内:$local_var"
}

local_demo  # 输出:函数内:局部变量
echo "函数外:$local_var"  # 输出:(空,外部无法访问)

4. 返回值:状态与数据的双重传递

4.1 返回码(状态值)
  • 用途:通过 return 声明,用于表示函数执行是否成功(0 = 成功,非 0 = 失败)。
  • 获取方式:调用后通过 $? 获取。
check_file() {
  if [ -e "$1" ]; then
    return 0  # 文件存在,返回成功码
  else
    return 1  # 文件不存在,返回错误码
  fi
}

check_file "test.sh"
if [ $? -eq 0 ]; then
  echo "文件存在"
else
  echo "文件不存在"
fi
4.2 数据返回(推荐方式)
  • 用途:通过 echo 或 printf 输出数据,适用于返回字符串、数值等复杂结果。
  • 获取方式:用命令替换 $(函数名) 接收输出。
get_current_time() {
  date +"%Y-%m-%d %H:%M:%S"  # 直接输出时间
}

time_now=$(get_current_time)
echo "当前时间:$time_now"  # 输出:当前时间:2023-10-01 15:30:00

5. 高级技巧:让函数更强大

5.1 函数递归:用循环逻辑解决复杂问题

场景:计算阶乘、斐波那契数列等递归问题。

# 计算 n 的阶乘(递归实现)
factorial() {
  local n=$1
  if [ $n -eq 0 ]; then
    echo 1  # 递归终止条件
  else
    echo $(( $n * $(factorial $((n-1))) ))  # 递归调用
  fi
}

result=$(factorial 5)
echo "5 的阶乘:$result"  # 输出:120
5.2 默认参数:让函数更 “智能”

语法:通过 ${参数:-默认值} 实现参数默认值。

greet() {
  local name=${1:-"Guest"}  # 若未传参,默认值为 "Guest"
  echo "Hello, $name!"
}

greet  # 输出:Hello, Guest!(未传参时用默认值)
greet "Alice"  # 输出:Hello, Alice!(传参时用实际值)
5.3 可变参数:处理不确定数量的输入

场景:函数需要接收任意数量的参数(如日志函数记录多个信息)。

log() {
  local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
  echo "[${timestamp}] $*"  # $* 表示所有参数(视为单个字符串)
}

log "用户登录" "IP: 192.168.1.1"  # 输出:[2023-10-01 15:30:00] 用户登录 IP: 192.168.1.1

6. 常见易错点与解决方案

6.1 忘记声明局部变量导致全局污染

错误示例

count=0  # 全局变量
increment() {
  count=$((count + 1))  # 未用 local,修改全局变量
}

increment
echo "全局 count:$count"  # 输出:1(全局变量被修改)

解决方案:在函数内用 local 声明变量:

increment() {
  local count=$((count + 1))  # 局部变量,不影响全局
}
6.2 参数索引错误(如 $0 误用)

错误示例

add() {
  echo $0  # 输出脚本名,而非第一个参数($0 是脚本名,参数从 $1 开始)
}

解决方案:牢记函数内参数从 $1 开始,$0 是脚本名。

6.3 返回码与数据返回混淆

错误做法:用 return 返回数据(仅支持 0-255 的整数)。

add() {
  return $((5 + 3))  # 错误,return 只能返回状态码
}

正确做法:用 echo 输出数据,return 仅用于状态码。

7. 实战案例:函数综合应用

7.1 文件操作函数库

需求:封装常用文件操作函数,如创建目录、复制文件。

#!/bin/bash

# 函数 1:创建目录(带错误处理)
create_dir() {
  local dir=$1
  if [ -d "$dir" ]; then
    echo "目录 $dir 已存在"
    return 1
  fi
  mkdir -p "$dir"
  if [ $? -eq 0 ]; then
    echo "目录 $dir 创建成功"
    return 0
  else
    echo "目录 $dir 创建失败"
    return 1
  fi
}

# 函数 2:复制文件到目录
copy_file() {
  local src=$1
  local dest_dir=$2
  if [ ! -f "$src" ]; then
    echo "源文件 $src 不存在"
    return 1
  fi
  if [ ! -d "$dest_dir" ]; then
    create_dir "$dest_dir"  # 调用其他函数
    if [ $? -ne 0 ]; then
      return 1
    fi
  fi
  cp "$src" "$dest_dir"
  echo "文件 $src 复制到 $dest_dir 成功"
  return 0
}

# 调用函数
copy_file "data.txt" "backup"
7.2 交互式菜单函数

需求:通过函数实现菜单驱动的用户交互。

show_menu() {
  echo "===== 菜单 ====="
  echo "1. 查看系统信息"
  echo "2. 退出程序"
  echo "================"
}

handle_choice() {
  local choice=$1
  case $choice in
    1)
      uname -a  # 显示系统信息
      ;;
    2)
      echo "退出程序"
      exit 0
      ;;
    *)
      echo "无效选择!"
      ;;
  esac
}

# 主程序
while true; do
  show_menu  # 调用菜单函数
  read -p "请选择:" choice
  handle_choice "$choice"  # 调用选择处理函数
done

8. 拓展知识:函数的进阶应用

8.1 函数库管理
  • 创建函数文件:将常用函数保存到独立文件(如 utils.sh)。
    # utils.sh 内容
    function add() { ... }
    function greet() { ... }
    
  • 引入函数库:通过 source 命令在脚本中引用。
    source utils.sh  # 使 utils.sh 中的函数在当前脚本生效
    add 5 3  # 直接调用
    
8.2 函数调试技巧
  • 开启调试模式:用 set -x 跟踪函数执行步骤。
    set -x  # 开启调试
    add 5 3  # 显示每一步执行的命令
    set +x  # 关闭调试
    
  • 打印参数信息:在函数开头输出参数,确认输入是否正确。
    add() {
      echo "接收到的参数:$1, $2"  # 调试用输出
      ...
    }
    

9. 总结:函数的 “复用哲学”

  • 代码复用:将重复逻辑封装为函数,避免 “重复造轮子”。
  • 模块化设计:每个函数专注于一个独立功能(如文件操作、数据计算),提高可维护性。
  • 错误处理:通过参数验证和返回码,让函数更健壮。

掌握函数后,你将从 “编写零散命令” 进阶到 “构建结构化脚本”。建议从简单函数开始,逐步积累常用工具函

八、实战案例:判断闰年

需求

输入年份,判断是否为闰年(闰年条件:能被 4 整除且不能被 100 整除,或能被 400 整除)。

脚本实现

#!/bin/bash
read -p "请输入年份:" year

# 组合条件:(year%400==0) 或 (year%4==0 且 year%100!=0)
if [ $((year % 400)) -eq 0 ] || [ ( $((year % 4)) -eq 0 -a $((year % 100)) -ne 0 ) ]; then
  echo "$year 是闰年"
else
  echo "$year 是平年"
fi

关键点

  • (` 和 `) 用于转义括号,确保条件正确组合。
  • || 表示逻辑或,-a 表示逻辑与。

九、常见易错点总结

  1. 变量赋值空格a = 10 错误,必须为 a=10(等号前后不能有空格)。
  2. 中括号空格[条件] 需写成 [ 条件 ],否则报错(如 [a -gt 5] 错误,应为 [ $a -gt 5 ])。
  3. 文件路径错误:执行脚本时需用 ./脚本名,直接输入 脚本名 会提示 “命令未找到”。
  4. 转义符遗漏:使用 expr 计算乘法时,* 需转义为 *,或改用 $(( )) 避免转义。
  5. 字符串比较误区:比较字符串是否相等时,= 前后需留空格(如 [ "$a" = "$b" ]),否则会被视为赋值。

十、总结

Shell 编程是 Linux 自动化的核心技能,从简单的脚本到复杂的流程控制,需要通过大量实践掌握。新手入门时,建议:

  1. 从单个知识点入手,如变量、循环、函数,逐个击破。
  2. 每学一个语法,编写小例子验证效果,理解背后逻辑。
  3. 遇到错误时,善用 echo 打印变量值,或用 bash -x 脚本名 调试(显示每行执行过程)。

记住:Shell 脚本的魅力在于 “用简单命令组合实现强大功能”,坚持练习,你会逐渐体会到它的高效与便捷!

本文地址:https://www.vps345.com/5602.html

搜索文章

Tags

PV计算 带宽计算 流量带宽 服务器带宽 上行带宽 上行速率 什么是上行带宽? CC攻击 攻击怎么办 流量攻击 DDOS攻击 服务器被攻击怎么办 源IP 服务器 linux 运维 游戏 云计算 javascript 前端 chrome edge python MCP llama 算法 opencv 自然语言处理 神经网络 语言模型 ssh 阿里云 网络 网络安全 网络协议 ubuntu deepseek Ollama 模型联网 API CherryStudio 进程 操作系统 进程控制 Ubuntu 数据库 centos oracle 关系型 安全 分布式 harmonyos 华为 开发语言 typescript 计算机网络 智能路由器 外网访问 内网穿透 端口映射 adb nginx 监控 自动化运维 django fastapi flask web3.py numpy flutter Hyper-V WinRM TrustedHosts web安全 Kali Linux 黑客 渗透测试 信息收集 笔记 C 环境变量 进程地址空间 tcp/ip github 创意 社区 Flask FastAPI Waitress Gunicorn uWSGI Uvicorn RTSP xop RTP RTSPServer 推流 视频 react.js 前端面试题 node.js 持续部署 ssl java android 鸿蒙 Dell R750XS 科技 ai 人工智能 个人开发 udp unity uni-app 面试 性能优化 jdk intellij-idea 架构 mcp mcp-proxy mcp-inspector fastapi-mcp agent sse ollama llm php golang GaN HEMT 氮化镓 单粒子烧毁 辐射损伤 辐照效应 pycharm ide pytorch rust http 前端框架 深度学习 YOLO 目标检测 计算机视觉 macos docker 容器 android studio .netcore gateway c++ Clion Nova ResharperC++引擎 Centos7 远程开发 live555 rtsp rtp 运维开发 json html5 firefox vim sqlserver kamailio sip VoIP 大数据 大数据平台 windows 微信 微信分享 Image wxopensdk 系统开发 binder 车载系统 framework 源码环境 conda pillow 统信 国产操作系统 虚拟机安装 WSL win11 无法解析服务器的名称或地址 websocket mysql 企业微信 Linux24.04 deepin tomcat kubernetes 学习方法 经验分享 程序人生 机器学习 低代码 后端 vscode 代码调试 ipdb asm HarmonyOS Next springsecurity6 oauth2 授权服务器 token sas av1 电视盒子 机顶盒ROM 魔百盒刷机 YOLOv12 DeepSeek-R1 API接口 3d 数学建模 express 多线程服务器 Linux网络编程 list 数据结构 visualstudio prometheus 开源 自动化 多进程 1024程序员节 ArcTS 登录 ArcUI GridItem kvm 无桌面 命令行 串口服务器 测试工具 向日葵 DigitalOcean GPU服务器购买 GPU服务器哪里有 GPU服务器 apache matlab Cline 搜索引擎 Deepseek mongodb 交互 c语言 mount挂载磁盘 wrong fs type LVM挂载磁盘 Centos7.9 微服务 springcloud 云原生 debian PVE 软件工程 嵌入式 linux驱动开发 arm开发 嵌入式硬件 c# mysql离线安装 ubuntu22.04 mysql8.0 dell服务器 go 代理模式 Windsurf IIS .net core Hosting Bundle .NET Framework vs2022 僵尸进程 rabbitmq es jvm 物联网 iot VMware安装Ubuntu Ubuntu安装k8s k8s 学习 媒体 微信公众平台 Qwen2.5-coder 离线部署 ollama下载加速 大模型 YOLOv8 NPU Atlas800 A300I pro asi_bench ecm bpm redis mybatis ping++ 深度优先 图论 并集查找 换根法 树上倍增 ddos qt stm32项目 单片机 stm32 minicom 串口调试工具 蓝耘科技 元生代平台工作流 ComfyUI chatgpt llama3 Chatglm 开源大模型 zotero WebDAV 同步失败 ansible playbook 宝塔面板访问不了 宝塔面板网站访问不了 宝塔面板怎么配置网站能访问 宝塔面板配置ip访问 宝塔面板配置域名访问教程 宝塔面板配置教程 温湿度数据上传到服务器 Arduino HTTP vue.js java-ee AI编程 华为云 集成学习 集成测试 银河麒麟服务器操作系统 系统激活 html 博客 elasticsearch jenkins sql KingBase oceanbase rc.local 开机自启 systemd 麒麟 负载均衡 AI 爬虫 数据集 kylin 智能手机 NAS Termux Samba Linux 银河麒麟 kylin v10 麒麟 v10 ffmpeg 音视频 ESP32 LDAP spring boot gitee postman mock mock server 模拟服务器 mock服务器 Postman内置变量 Postman随机数据 maven intellij idea audio vue音乐播放器 vue播放音频文件 Audio音频播放器自定义样式 播放暂停进度条音量调节快进快退 自定义audio覆盖默认样式 nuxt3 vue3 实时音视频 dubbo bash .net fpga开发 openEuler unity3d spring 计算机外设 电脑 mac 软件需求 Docker Compose docker compose docker-compose gitlab HCIE 数通 大模型微调 腾讯云 filezilla 无法连接服务器 连接被服务器拒绝 vsftpd 331/530 wsl2 wsl jmeter 软件测试 业界资讯 dify 鲲鹏 技能大赛 git 系统安全 code-server MQTT mosquitto 消息队列 selete 高级IO Headless Linux postgresql pgpool 多层架构 解耦 microsoft 田俊楠 RAID RAID技术 磁盘 存储 华为od sqlite 华为认证 网络工程师 交换机 MS Materials openssl 密码学 Agent LLM 课程设计 产品经理 agi 自定义客户端 SAS shell outlook ci/cd 政务 分布式系统 监控运维 Prometheus Grafana flink echarts 信息可视化 数据分析 网页设计 华为机试 C++ Java Python skynet excel virtualenv ceph 安全架构 Trae AI代码编辑器 硬件架构 GCC Linux环境 https AISphereButler AI大模型 程序员 armbian u-boot LORA 大语言模型 NLP LInux remote-ssh rocketmq 其他 编辑器 r语言 ukui 麒麟kylinos openeuler rust腐蚀 npm 框架搭建 缓存 深度求索 私域 知识库 游戏程序 交叉编译 jar tcpdump Linux PID 回显服务器 UDP的API使用 gpt-3 文心一言 MacMini Mac 迷你主机 mini Apple ruoyi springboot etcd 数据安全 RBAC ftp web 宠物 毕业设计 免费学习 宠物领养 宠物平台 云服务器 VPS pyqt frp 小程序 微信小程序域名配置 微信小程序服务器域名 微信小程序合法域名 小程序配置业务域名 微信小程序需要域名吗 微信小程序添加域名 小艺 Pura X 腾讯云大模型知识引擎 EasyConnect zabbix ui RustDesk自建服务器 rustdesk服务器 docker rustdesk URL 昇腾 npu opensearch helm 服务器主板 AI芯片 信息与通信 HTML audio 控件组件 vue3 audio音乐播放器 Audio标签自定义样式默认 vue3播放音频文件音效音乐 自定义audio播放器样式 播放暂停调整声音大小下载文件 MI300x DeepSeek 孤岛惊魂4 WebRTC gpt openwrt OD机试真题 华为OD机试真题 服务器能耗统计 tcp ux 多线程 vscode1.86 1.86版本 ssh远程连接 pip open Euler dde 统信UOS 报错 RTMP 应用层 jupyter LLM Web APP Streamlit hadoop big data svn opcua opcda KEPServer安装 open webui unix VR手套 数据手套 动捕手套 动捕数据手套 springboot远程调试 java项目远程debug docker远程debug java项目远程调试 springboot远程 string模拟实现 深拷贝 浅拷贝 经典的string类问题 三个swap Reactor 设计模式 游戏服务器 TrinityCore 魔兽世界 服务器数据恢复 数据恢复 存储数据恢复 北亚数据恢复 oracle数据恢复 sysctl.conf vm.nr_hugepages adobe 传统数据库升级 银行 JAVA spring cloud 单一职责原则 kafka 网络编程 聊天服务器 套接字 TCP 客户端 Socket webrtc IPMITOOL BMC 硬件管理 FTP 服务器 XCC Lenovo 崖山数据库 YashanDB 视频编解码 源码剖析 rtsp实现步骤 流媒体开发 繁忙 服务器繁忙 解决办法 替代网站 汇总推荐 AI推理 网络结构图 uniapp Ubuntu 24.04.1 轻量级服务器 NFS redhat dba gpu算力 命名管道 客户端与服务端通信 pdf asp.net大文件上传 asp.net大文件上传下载 asp.net大文件上传源码 ASP.NET断点续传 asp.net上传文件夹 asp.net上传大文件 .net core断点续传 群晖 文件分享 中间件 iis 7z VSCode 移动云 devops 云服务 NPS 雨云服务器 雨云 可信计算技术 输入法 raid5数据恢复 磁盘阵列数据恢复 僵尸世界大战 游戏服务器搭建 远程控制 远程看看 远程协助 银河麒麟操作系统 国产化 远程 命令 执行 sshpass 操作 zookeeper saltstack 服务器部署ai模型 prompt DevEco Studio embedding 部署 SSL 域名 rsyslog Anolis nginx安装 环境安装 linux插件下载 高效日志打印 串口通信日志 服务器日志 系统状态监控日志 异常记录日志 v10 镜像源 软件 firewalld minio 鸿蒙系统 arkUI IDE AI 原生集成开发环境 Trae AI aws mcu 网络攻击模型 驱动开发 硬件工程 嵌入式实习 ecmascript KVM eureka ipython AIGC chrome devtools selenium chromedriver n8n 工作流 workflow 三级等保 服务器审计日志备份 Cursor css 本地部署 api wireshark 架构与原理 联想开天P90Z装win10 Kylin-Server 服务器安装 机器人 多个客户端访问 IO多路复用 TCP相关API gcc g++ g++13 Cookie bootstrap 系统架构 nextjs react reactjs 黑客技术 微信小程序 流式接口 开机自启动 网工 压测 ECS easyui langchain ssrf 失效的访问控制 camera Arduino 电子信息 Portainer搭建 Portainer使用 Portainer使用详解 Portainer详解 Portainer portainer ue4 着色器 ue5 虚幻 Google pay Apple pay IDEA SSE 目标跟踪 OpenVINO 推理应用 语法 yum源切换 更换国内yum源 vue vue-i18n 国际化多语言 vue2中英文切换详细教程 如何动态加载i18n语言包 把语言json放到服务器调用 前端调用api获取语言配置文件 QQ bot Docker xrdp 远程桌面 远程连接 系统 黑苹果 虚拟机 VMware pygame 小游戏 五子棋 sdkman Unity Dedicated Server Host Client 无头主机 开发环境 SSL证书 数据库架构 数据管理 数据治理 数据编织 数据虚拟化 nvidia elk tidb GLIBC 能力提升 面试宝典 技术 IT信息化 环境迁移 cuda cudnn thingsboard ESXi 视觉检测 DNS ip命令 新增网卡 新增IP 启动网卡 VMware创建虚拟机 职场和发展 自动化测试 性能测试 功能测试 odoo 服务器动作 Server action alias unalias 别名 相差8小时 UTC 时间 源码 netty rpc 远程过程调用 Windows环境 混合开发 JDK regedit 开机启动 直播推流 指令 远程工作 策略模式 单例模式 支付 微信支付 开放平台 cpu 内存 实时 使用 毕设 midjourney AI写作 进程信号 CLion FTP服务器 word图片自动上传 word一键转存 复制word图片 复制word图文 复制word公式 粘贴word图文 粘贴word公式 状态管理的 UDP 服务器 Arduino RTOS 跨域 yum hive Hive环境搭建 hive3环境 Hive远程模式 gitea risc-v arm wordpress 无法访问wordpess后台 打开网站页面错乱 linux宝塔面板 wordpress更换服务器 centos-root /dev/mapper yum clean all df -h / du -sh C语言 佛山戴尔服务器维修 佛山三水服务器维修 京东云 threejs 3D 设置代理 实用教程 版本 安装 Invalid Host allowedHosts rdp 实验 Dify gradle linux 命令 sed 命令 Wi-Fi 计算机 干货分享 黑客工具 密码爆破 C# MQTTS 双向认证 emqx 技术共享 软考 flash-attention UOS 统信操作系统 SysBench 基准测试 C++软件实战问题排查经验分享 0xfeeefeee 0xcdcdcdcd 动态库加载失败 程序启动失败 程序运行权限 标准用户权限与管理员权限 WebUI DeepSeek V3 云电竞 云电脑 todesk 宕机切换 服务器宕机 bonding 链路聚合 权限 数据挖掘 压力测试 执法记录仪 智能安全帽 smarteye tailscale derp derper 中转 矩阵 线性代数 电商平台 cursor 音乐服务器 Navidrome 音流 MCP server C/S windows日志 transformer idm Minecraft 飞牛NAS 飞牛OS MacBook Pro DOIT 四博智联 lua cnn Ubuntu Server Ubuntu 22.04.5 宝塔面板 H3C Dell HPE 联想 浪潮 iDRAC R720xd freebsd 前后端分离 ocr 服务器无法访问 ip地址无法访问 无法访问宝塔面板 宝塔面板打不开 XFS xfs文件系统损坏 I_O error 测试用例 磁盘监控 kind 数据可视化 next.js 部署next.js 聊天室 iftop 网络流量监控 服务器配置 生物信息学 Open WebUI bug 怎么卸载MySQL MySQL怎么卸载干净 MySQL卸载重新安装教程 MySQL5.7卸载 Linux卸载MySQL8.0 如何卸载MySQL教程 MySQL卸载与安装 FunASR ASR 剧本 file server http server web server ios iphone muduo X11 Xming 弹性计算 虚拟化 计算虚拟化 弹性裸金属 Linux awk awk函数 awk结构 awk内置变量 awk参数 awk脚本 awk详解 安卓 Docker Hub docker pull daemon.json 王者荣耀 Ubuntu 24 常用命令 Ubuntu 24 Ubuntu vi 异常处理 Spring Security mariadb c Linux无人智慧超市 LInux多线程服务器 QT项目 LInux项目 单片机项目 grafana 远程登录 telnet ISO镜像作为本地源 文件系统 路径解析 硬件 设备 GPU PCI-Express Claude 阻塞队列 生产者消费者模型 服务器崩坏原因 jetty undertow mamba Vmamba SSH efficientVIT YOLOv8替换主干网络 TOLOv8 p2p Erlang OTP gen_server 热代码交换 事务语义 MNN Qwen DenseNet ip MacOS录屏软件 备份SQL Server数据库 数据库备份 傲梅企业备份网络版 hugo RAGFLOW RAG 检索增强生成 文档解析 大模型垂直应用 Netty 即时通信 NIO SWAT 配置文件 服务管理 网络共享 HTTP 服务器控制 ESP32 DeepSeek gaussdb 银河麒麟桌面操作系统 Kylin OS DeepSeek行业应用 Heroku 网站部署 xss GoogLeNet 游戏机 pppoe radius USB网络共享 监控k8s集群 集群内prometheus .net mvc断点续传 micropython esp32 mqtt AI agent 思科模拟器 思科 Cisco 医疗APP开发 app开发 vasp安装 5G 3GPP 卫星通信 AutoDL AI作画 IIS服务器 IIS性能 日志监控 WSL2 模拟退火算法 服务器管理 配置教程 网站管理 国标28181 视频监控 监控接入 语音广播 流程 SIP SDP vmware 卡死 算力 googlecloud TCP服务器 qt项目 qt项目实战 qt教程 工业4.0 银河麒麟高级服务器 外接硬盘 Kylin linux安装配置 windwos防火墙 defender防火墙 win防火墙白名单 防火墙白名单效果 防火墙只允许指定应用上网 防火墙允许指定上网其它禁止 根服务器 clickhouse kali 共享文件夹 社交电子 数据库系统 protobuf 序列化和反序列化 ai小智 语音助手 ai小智配网 ai小智教程 智能硬件 esp32语音助手 diy语音助手 EMQX 通信协议 hibernate laravel 大模型入门 大模型教程 小智AI服务端 xiaozhi TTS 直流充电桩 充电桩 IPMI eNSP 网络规划 VLAN 企业网络 显示过滤器 ICMP Wireshark安装 junit 强制清理 强制删除 mac废纸篓 AD 域管理 W5500 OLED u8g2 网站搭建 serv00 chfs ubuntu 16.04 linux环境变量 漏洞 微信开放平台 微信公众号配置 同步 备份 建站 安全威胁分析 vscode 1.86 自动驾驶 perf 火绒安全 xml Nuxt.js Xterminal Ark-TS语言 网络用户购物行为分析可视化平台 大数据毕业设计 需求分析 规格说明书 豆瓣 追剧助手 迅雷 nas 裸金属服务器 弹性裸金属服务器 k8s资源监控 annotations自动化 自动化监控 监控service 监控jvm 安装教程 GPU环境配置 Ubuntu22 CUDA PyTorch Anaconda安装 网络穿透 飞书 dns openstack Xen 上传视频至服务器代码 vue3批量上传多个视频并预览 如何实现将本地视频上传到网页 element plu视频上传 ant design vue vue3本地上传视频及预览移除 恒源云 备选 网站 调用 示例 AD域 vSphere vCenter 软件定义数据中心 sddc 反向代理 图形化界面 致远OA OA服务器 服务器磁盘扩容 CPU 主板 电源 网卡 cmos okhttp CORS oneapi TRAE Logstash 日志采集 crosstool-ng 重启 排查 系统重启 日志 原因 Playwright 半虚拟化 硬件虚拟化 Hypervisor LLMs 边缘计算 VMware安装mocOS macOS系统安装 nac 802.1 portal EtherNet/IP串口网关 EIP转RS485 EIP转Modbus EtherNet/IP网关协议 EIP转RS485网关 EIP串口服务器 无人机 ROS 聚类 Ubuntu共享文件夹 共享目录 Linux共享文件夹 程序 编程 性能分析 安防软件 端口测试 wpf MVS 海康威视相机 软件构建 图像处理 deekseek ragflow CDN RAGFlow 分析解读 wsgiref Web 服务器网关接口 yaml Ultralytics 可视化 fstab ABAP 实时互动 虚拟局域网 java-rocketmq 做raid 装系统 Java Applet URL操作 服务器建立 Socket编程 网络文件读取 本地部署AI大模型 ardunio BLE webstorm 显卡驱动 visual studio code 大模型应用 Jellyfin 存储维护 NetApp存储 EMC存储 OpenSSH 云桌面 微软 AD域控 证书服务器 大大通 第三代半导体 碳化硅 TrueLicense 信号 SSH 密钥生成 SSH 公钥 私钥 生成 主从复制 项目部署到linux服务器 项目部署过程 升级 CVE-2024-7347 rustdesk react native 金融 cd 目录切换 seatunnel 超融合 双系统 h.264 容器技术 序列化反序列化 jina IPv4 子网掩码 公网IP 私有IP 匿名管道 docker搭建pg docker搭建pgsql pg授权 postgresql使用 postgresql搭建 产测工具框架 IMX6ULL 管理框架 iperf3 带宽测试 web3 游戏引擎 Linux的基础指令 composer cpp-httplib 程序员创富 docker搭建nacos详解 docker部署nacos docker安装nacos 腾讯云搭建nacos centos7搭建nacos IMM 智能音箱 智能家居 代码 对比 工具 meld Beyond Compare DiffMerge 开发 蓝桥杯 spark HistoryServer Spark YARN jobhistory MQTT协议 消息服务器 python3.11 HarmonyOS lio-sam SLAM uv glibc wps Redis Desktop keepalived sonoma 自动更新 IM即时通讯 剪切板对通 HTML FORMAT ubuntu24.04.1 xshell termius iterm2 nfs sqlite3 自学笔记 小米 澎湃OS Android IO模型 HiCar CarLife+ CarPlay QT RK3588 ruby yolov8 Node-Red 编程工具 流编程 xcode ldap 读写锁 AI Agent 字节智能运维 服务网格 istio rclone AList webdav fnOS rnn GIS 遥感 WebGIS 阿里云ECS fast 端口 查看 ss deployment daemonset statefulset cronjob Windows ai工具 matplotlib 合成模型 扩散模型 图像生成 内网环境 软件卸载 系统清理 arcgis rag ragflow 源码启动 OpenHarmony 真机调试 运维监控 safari 小番茄C盘清理 便捷易用C盘清理工具 小番茄C盘清理的优势尽显何处? 教你深度体验小番茄C盘清理 C盘变红?!不知所措? C盘瘦身后电脑会发生什么变化? 历史版本 下载 IMX317 MIPI H265 VCU pyautogui etl 网卡的名称修改 eth0 ens33 ShenTong triton 模型分析 less 大文件分片上传断点续传及进度条 如何批量上传超大文件并显示进度 axios大文件切片上传详细教 node服务器合并切片 vue3大文件上传报错提示错误 大文件秒传跨域报错cors 图形渲染 anaconda 线程 SRS 流媒体 直播 Linux find grep 钉钉 防火墙 NAT转发 NAT Server sequoiaDB Deepseek-R1 私有化部署 推理模型 代理 onlyoffice 捆绑 链接 谷歌浏览器 youtube google gmail OpenManus c/c++ 串口 常用命令 文本命令 目录命令 抓包工具 prometheus数据采集 prometheus数据模型 prometheus特点 宝塔 相机 dash 正则表达式 db DeepSeek r1 AI-native Docker Desktop fd 文件描述符 tensorflow css3 eclipse sentinel 知识图谱 用户缓冲区 模拟实现 x64 SIGSEGV xmm0 信创 信创终端 中科方德 PX4 miniapp 调试 debug 断点 网络API请求调试方法 apt 国内源 李心怡 SenseVoice webgl vpn 办公自动化 自动化生成 pdf教程 考研 在线office xpath定位元素 curl wget bat cocoapods 基础入门 swoole chrome 浏览器下载 chrome 下载安装 谷歌浏览器下载 MacOS 私有化 我的世界服务器搭建 Ubuntu DeepSeek DeepSeek Ubuntu DeepSeek 本地部署 DeepSeek 知识库 DeepSeek 私有化知识库 本地部署 DeepSeek DeepSeek 私有化部署 加解密 Yakit yaklang 强化学习 RoboVLM 通用机器人策略 VLA设计哲学 vlm fot robot 视觉语言动作模型 具身智能 我的世界 我的世界联机 数码 UDP 自动化任务管理 服务器时间 MySql 流量运营 KylinV10 麒麟操作系统 Vmware 软链接 硬链接 SSH 服务 SSH Server OpenSSH Server epoll 带外管理 企业网络规划 华为eNSP aarch64 编译安装 HPC Ubuntu22.04 开发人员主页 EtherCAT转Modbus ECT转Modbus协议 EtherCAT转485网关 ECT转Modbus串口网关 EtherCAT转485协议 ECT转Modbus网关 移动魔百盒 trea idea USB转串口 CH340 harmonyOS面试题 iBMC UltraISO 邮件APP 免费软件 飞牛nas fnos log4j 域名服务 DHCP 符号链接 配置 音乐库 飞牛 Xinference vr 树莓派 VNC Unity插件 免费域名 域名解析 iventoy VmWare OpenEuler docker命令大全 Kali DocFlow mq 链表 键盘 ubuntu24 vivado24 deepseek r1 su sudo 代理服务器 uni-file-picker 拍摄从相册选择 uni.uploadFile H5上传图片 微信小程序上传图片 make命令 makefile文件 粘包问题 Linux的权限 perl 个人博客 k8s集群资源管理 云原生开发 rtsp服务器 rtsp server android rtsp服务 安卓rtsp服务器 移动端rtsp服务 大牛直播SDK Python基础 Python教程 Python技巧 edge浏览器 AP配网 AK配网 小程序AP配网和AK配网教程 WIFI设备配网小程序UDP开 镜像 影刀 #影刀RPA# 监控k8s 监控kubernetes grub 版本升级 扩容 大模型面经 大模型学习 AnythingLLM AnythingLLM安装 游戏开发 显示管理器 lightdm gdm navicat 实习 figma rime qemu libvirt WebVM 基础环境 流水线 脚本式流水线 Attention 磁盘镜像 服务器镜像 服务器实时复制 实时文件备份 信号处理 Typore CrewAI 单元测试 查看显卡进程 fuser 并查集 leetcode win服务器架设 windows server 金仓数据库 2025 征文 数据库平替用金仓 dns是什么 如何设置电脑dns dns应该如何设置 在线预览 xlsx xls文件 在浏览器直接打开解析xls表格 前端实现vue3打开excel 文件地址url或接口文档流二进 can 线程池 迁移指南 串口驱动 CH341 uart 485 llama.cpp minecraft ssh远程登录 查询数据库服务IP地址 SQL Server 分布式训练 问题解决 bcompare 网络药理学 生信 gromacs 分子动力学模拟 MD 动力学模拟 模拟器 教程 docker run 数据卷挂载 交互模式 SVN Server tortoise svn 自动化编程 Radius 浏览器开发 AI浏览器 ssh漏洞 ssh9.9p2 CVE-2025-23419 状态模式 HAProxy EMUI 回退 降级 ros2 moveit 机器人运动 物联网开发 proxy模式 烟花代码 烟花 元旦 性能调优 安全代理 本地知识库部署 DeepSeek R1 模型 高效远程协作 TrustViewer体验 跨设备操作便利 智能远程控制 UOS1070e VS Code lsb_release /etc/issue /proc/version uname -r 查看ubuntu版本 dity make 中兴光猫 换光猫 网络桥接 自己换光猫 SEO ArkUI 多端开发 智慧分发 应用生态 鸿蒙OS hexo powerpoint 环境配置 Docker引擎已经停止 Docker无法使用 WSL进度一直是0 镜像加速地址 人工智能生成内容 内网服务器 内网代理 内网通信 VM搭建win2012 win2012应急响应靶机搭建 攻击者获取服务器权限 上传wakaung病毒 应急响应并溯源 挖矿病毒处置 应急响应综合性靶场 DBeaver 数据仓库 kerberos 灵办AI 实战案例 searxng 互信 毕昇JDK firewall cfssl TCP协议 autodl 元服务 应用上架 抗锯齿 换源 Debian 虚拟显示器 GRUB引导 Linux技巧 trae ros P2P HDLC 语音识别 milvus linux上传下载 QT 5.12.12 QT开发环境 Ubuntu18.04 健康医疗 互联网医院 项目部署 推荐算法 HarmonyOS NEXT 原生鸿蒙 dock 加速 neo4j 风扇控制软件 ubuntu20.04 ros1 Noetic 20.04 apt 安装 CentOS Stream CentOS seleium top Linux top top命令详解 top命令重点 top常用参数 达梦 DM8 西门子PLC 通讯 端口聚合 windows11 热榜 docker desktop image 数据库开发 database 软负载 js word rpa 鸿蒙开发 移动开发 解决方案 搭建个人相关服务器 网络建设与运维 数字证书 签署证书 本地化部署 智能电视 MDK 嵌入式开发工具 论文笔记 sublime text docker部署翻译组件 docker部署deepl docker搭建deepl java对接deepl 翻译组件使用 离线部署dify 玩机技巧 软件分享 软件图标 渗透 docker部署Python ArkTs kernel nlp Mac内存不够用怎么办 欧标 OCPP 服务器正确解析请求体 kotlin IO 嵌入式系统开发 WLAN deep learning vllm Qwen2.5-VL 远程服务 yum换源 conda配置 conda镜像源 nosql 网络爬虫 开机黑屏 稳定性 看门狗 大模型推理 大模型部署 沙盒 ArtTS 增强现实 沉浸式体验 应用场景 技术实现 案例分析 AR 虚幻引擎 论文阅读 代码托管服务 gnu nvm whistle 嵌入式Linux IPC 网络搭建 神州数码 神州数码云平台 云平台 磁盘清理 mm-wiki搭建 linux搭建mm-wiki mm-wiki搭建与使用 mm-wiki使用 mm-wiki详解 visual studio macOS hosts PPI String Cytoscape CytoHubba ranger MySQL8.0 拓扑图 多路转接