本文为 Linux 软件编程学习首日完整笔记,涵盖操作系统基础概念、Linux 内核架构、Shell 常用命令、Shell 脚本分支语法,同时整理了实操过程中最容易踩的语法坑与逻辑坑,零基础入门可直接参考避坑,适合嵌入式、服务器开发方向的初学者。


一、操作系统与 Linux 核心基础

1. 操作系统的本质

操作系统是一款系统级软件,核心作用是屏蔽底层不同硬件平台的差异,为上层应用提供统一的调用接口,让同一份软件代码可以在不同硬件上通用运行。

2. PC 端三大操作系统对比

系统 核心特点 开发语言 主流应用场景
Unix 世界上第一款现代操作系统,稳定性极强 C 语言 高端服务器、工作站
Linux 开源免费,遵循 GNU 协议(GNU's Not Unix) C 语言 服务器、嵌入式开发
Windows 闭源商用,图形化交互友好 C/C++ 桌面办公、消费级 PC

3. Linux 内核五大核心功能

  1. 内存管理:管控系统内存的分配、回收与保护
  2. 多任务调度:分配 CPU 时间片,调度多个进程并发执行
  3. 文件系统管理:Linux 核心设计思想 ——一切皆是文件,所有硬件、资源都以文件形式对外提供接口
  4. 多任务间通信:提供进程间数据交互的机制
  5. 网络通信:实现网络协议栈,完成网络数据收发

4. 内核、Shell、库函数的层级关系

  • Linux 内核:由纯 C 代码实现的系统调用集合,不允许用户直接交互,功能底层但调用门槛高
  • Shell(命令解释器):对内核功能做一层封装,用户通过输入命令间接调用内核,同时起到保护内核的作用
  • 库函数:对系统调用的二次封装,可处理更复杂的应用场景;具备可移植性,跨平台通用

二、Shell 常用命令汇总

1. 文件与目录基础操作

命令 功能 常用参数与注意事项
ls 列出目录内容 -l 查看详细信息;-a 显示隐藏文件
touch 创建空文件
rm 删除文件 / 目录 -rf 递归强制删除非空目录
mkdir 创建目录(文件夹)
rmdir 删除空目录 只能删空文件夹
cp 拷贝文件 拷贝目录需搭配 -rf 参数
mv 移动文件 / 重命名文件

Linux 七种文件类型(ls -l 首字符标识)

  • b:块设备文件(block),如硬盘、U 盘等存储设备
  • c:字符设备文件(character),如键盘、终端等流式设备
  • d:目录文件(directory),即文件夹
  • -:普通文件,如文本、脚本、可执行程序
  • l:链接文件(link),分为软链接和硬链接
  • s:套接字文件(socket),用于进程间网络通信
  • p:管道文件(pipe),用于进程间单向通信

2. 文件查看命令

  1. cat 文件名:直接输出文件全部内容,适合小文件
  2. more / less:分页查看大文件,less 支持上下自由翻页
  3. head / tail:查看文件首尾指定行数

    bash

    head -n 行数 文件名
    tail -n 行数 文件名
    

3. 文件查找与内容匹配

  1. find:按文件名递归查找文件路径
    <p>bash</p>
    
    find . -name "目标文件名"   # 在当前目录递归查找
    
  2. grep:在文件中查找包含指定字符串的行

    bash

    grep "目标字符串" 文件名
    

4. 通配符语法

符号 作用 示例
* 匹配任意长度、任意字符 file_*.txt
? 匹配 1 位任意字符 file_??.txt
[] 匹配 1 位指定范围内字符 file_[1,3,5].txtfile_[1-5].txt
[^] 匹配 1 位不在指定范围内字符 file_[^6].txt

5. tar 压缩与解压

gzip 格式(.tar.gz
# 压缩
tar -zcvf 压缩包名.tar.gz 目标路径/*
# 解压
tar -zxvf 压缩包名.tar.gz
bzip2 格式(.tar.bz2
# 压缩
tar -jcvf 压缩包名.tar.bz2 目标路径/*
# 解压
tar -jxvf 压缩包名.tar.bz2

6. 管道与重定向

  1. 管道 |:将前一条命令的输出,作为后一条命令的输入
    <pre>
    

    ps -ef | grep "bash" # 查找系统中bash相关的进程

  2. 重定向
    • >:覆盖重定向,清空原文件内容后写入
    • >>:追加重定向,在文件末尾追加内容
    ps -ef > file.txt   # 将进程列表写入file.txt,覆盖原有内容
    

经典练习题:在/usr/include/stdio.h的后 200 行中,查找包含extern的行并保存到file.txt

tail -n 200 /usr/include/stdio.h | grep "extern" > file.txt

7. 其他常用工具命令

  • echo:在终端输出指定内容
  • history:查看终端历史输入的命令
  • du:查看文件 / 目录大小,-m以 MB 为单位,-k以 KB 为单位
  • od:按指定格式查看文件二进制内容,如 od -c 文件名
  • date:查看系统日期与时间
  • uname -a:查看内核版本与系统架构
  • ifconfig:查看网卡信息
  • ping IP地址:测试主机与目标 IP 的网络连通性

8. 软件包管理

dpkg 工具(本地 deb 包安装)
sudo dpkg -i 软件包名.deb    # 安装本地deb包
sudo dpkg -P 软件名          # 彻底卸载软件
dpkg -l 软件名               # 查看软件是否安装成功
apt-get 工具(联网在线安装)
sudo apt-get install 软件名        # 下载并安装软件
sudo apt-get remove 软件名 --purge # 彻底卸载软件

三、Shell 脚本编程入门

1. 编译型 vs 解释型语言

类型 核心特点 执行速度 开发效率 适用场景
编译型 有丰富数据类型,先编译再执行 数据运算、高性能开发
解释型 所有内容默认都是字符串,边解释边执行 系统运维、自动化脚本

Shell 脚本属于解释型语言,本质就是一系列 Shell 命令的逻辑化集合。

2. Shell 脚本编写执行三步法

  1. 编写脚本代码:vim 脚本名.sh,首行固定写 #!/bin/bash 指定解释器
  2. 添加执行权限:chmod +x 脚本名.sh
  3. 运行脚本:./脚本名.sh

3. Shell 三类变量

(1)环境变量:系统预置的全局变量
  • $PWD:当前工作目录,等价于 pwd 命令
  • $HOME:当前用户的家目录
  • $PATH:系统命令搜索路径,多个目录用冒号分隔
(2)位置变量:接收脚本执行时的命令行参数
变量 含义
$0 脚本自身的文件名
$1 / $2 / $3 第 1/2/3 个命令行参数
$# 传入参数的总个数
$$ 当前脚本运行的进程 PID
$? 上一条命令的退出状态码,0 表示成功,非 0 表示失败

注意:位置参数只能通过执行脚本时命令行后跟参数传入,写在脚本代码内部无效。

(3)自定义变量
  • 定义:变量名=值(等号两边不能有空格)
  • 取值:$变量名

4. 三种引号的区别

  1. 双引号 ":会解析内部变量,将变量替换为对应的值
  2. 单引号 ':原样输出内部所有内容,不解析变量
  3. 反引号 `:将内部内容作为 Shell 命令执行,返回执行结果

5. 输入与输出

  • 输出:echo 内容
  • 输入:read 变量名,接收终端用户输入;可加 -p 参数添加提示语
    read -p "请输入文件名:" filename
    

6. if 分支语句

基础语法
if [ 条件 ]
then
    满足条件执行的语句
elif [ 条件2 ]
then
    满足条件2执行的语句
else
    都不满足执行的语句
fi
常用条件判断类型
  • 数字比较:-gt 大于、-lt 小于、-eq 等于、-ne 不等于
  • 文件判断:-e 存在、-f 普通文件、-d 目录、-b 块设备、-c 字符设备
  • 字符串比较:= 相等、!= 不相等

7. case 多分支语句

适合固定值匹配的场景,语法更简洁清晰

case 变量 in
值1)
    执行语句1
    ;;
值2)
    执行语句2
    ;;
*)
    兜底默认语句
    ;;
esac
  • ;; 表示当前分支执行结束
  • *) 相当于 else,匹配所有其他情况
  • esac 是 case 的反向拼写,作为结构结束标记

四、实操高频踩坑避坑指南(核心干货)

坑 1:if 与 [之间缺少空格 → command not found

❌ 错误写法

if[ $num -gt 10 ]

✅ 正确写法

if [ $num -gt 10 ]

原因:[ 本质是一个独立的 test 命令,前后必须有空格,否则 Shell 会将if[识别为一个不存在的命令。

坑 2:echo 与字符串之间无空格

❌ 错误写法

echo"优秀"

✅ 正确写法

echo "优秀"

坑 3:-e放在 if 首位,导致后续 elif 全部失效

❌ 错误逻辑

if [ -e "$file" ]
then
    echo "存在"
elif [ -f "$file" ]  # 永远不会执行
then
    echo "普通文件"
fi

原因:-e 只要文件存在就为真,普通文件、目录、设备文件都会命中第一个 if,后续 elif 直接跳过。

✅ 正确逻辑

if [ ! -e "$file" ]
then
    echo "文件不存在"
elif [ -f "$file" ]
then
    echo "普通文件"
elif [ -d "$file" ]
then
    echo "目录"
fi

坑 4:条件判断中变量不加双引号

❌ 隐患写法

if [ -f $file ]

✅ 规范写法

if [ -f "$file" ]

原因:当文件名包含空格时,无引号会导致变量展开后被拆分成多个参数,语法报错;加双引号会将内容作为一个整体。

坑 5:位置参数写在脚本内部无效

脚本内写 echo $1 100 20 70 不会让$1等于 100。位置参数必须在执行脚本时通过命令行传入:

./脚本名.sh 100 20 70

坑 6:成绩分级 case 漏处理 100 分场景

❌ 漏洞写法

num=`expr $score / 10`
case $num in
    9) echo "优秀" ;;

100 分除以 10 得到 10,无法匹配 9,会落入兜底判为不及格。

✅ 兼容写法

case $num in
    10|9) echo "优秀" ;;

坑 7:mkdir 不加 - p,目录已存在时报错

❌ 隐患写法

mkdir tmp

✅ 健壮写法

mkdir -p tmp

-p 参数:目录不存在则创建,已存在也不会报错,工程代码中推荐使用。

五、实战脚本完整示例

示例 1:输入文件名,判断文件类型

#!/bin/bash
read -p "请输入文件路径:" file
if [ ! -e "$file" ]
then
echo "文件/目录不存在"
elif [ -f "$file" ]
then
echo "普通文件"
elif [ -d "$file" ]
then
echo "目录文件"
elif [ -b "$file" ]
then
echo "块设备文件"
elif [ -c "$file" ]
then
echo "字符设备文件"
fi

示例 2:case 实现成绩等级判定

#!/bin/bash
read -p "请输入分数:" score
num=`expr $score / 10`
case $num in
10|9) echo "优秀" ;;
8) echo "良好" ;;
7) echo "中等" ;;
6) echo "及格" ;;
*) echo "不及格" ;;
esac

示例 3:指定文件名条件处理脚本

#!/bin/bash
read -p "请输入文件名:" filename
if [ "$filename" = "qianrushi" ]
then
if [ -e "$filename" ]
then
mkdir -p tmp
touch tmp/qianrushi.txt
echo "文件存在,已创建tmp目录与tmp/qianrushi.txt"
else
touch "$filename"
echo "文件不存在,已直接创建"
fi
fi

六、Day1 学习总结

第一天学习从操作系统底层概念入手,建立了 “Linux 一切皆是文件” 的核心认知,掌握了常用 Shell 命令的使用场景,同时入门了 Shell 脚本的变量、分支语法。

Shell 语法和常规编程语言差异最大的地方在于空格规范引号使用,这也是初学者最高频的报错点;其次是条件判断的逻辑顺序,比如-e不能放在分支首位。掌握这些避坑点,能大幅减少脚本调试时间。

后续会继续学习循环、函数等进阶语法,逐步掌握 Shell 自动化脚本开发。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐