跳转至

网安协会第二次内部培训-Linux系统的安装和Shell基础

Liunx 介绍

Linux 系统泛指一系列基于 Linux 内核的操作系统。 每个基于 Linux 的操作系统都包含 Linux 内核(管理着硬件资源)和一组软件包(构成了操作系统的其余部分)。由于于其开源特性,Linux 具有高度的可定制性和广泛的应用范围,从服务器、桌面电脑到嵌入式系统和移动设备。Linux 系统的安全性、稳定性和良好的性能使它成为服务器和开发环境中的重要选择。

alt text

Linux由全球的开发者和组织共同维护,主要包括:

  • Linus Torvalds:Linux内核的创始人,负责核心代码的管理。
  • 核心开发团队:负责各个内核模块的维护和改进。
  • Linux基金会:提供支持、协调开发,促进企业和开发者的合作。
  • 企业贡献者:一些公司(如Red Hat、Intel等)雇佣开发者参与Linux开发,优化硬件支持和系统性能。
  • 开源社区:由志愿者和独立开发者组成,贡献代码和反馈。

Ubuntu是一个以桌面应用为主的Linux发行版操作系统,包含了Linux内核,GNU函数库和各种系统工具,命令行Shell,图形界面底层的X窗口系统和上层的桌面环境等。 由于其便于安装和使用,已经成为最广泛使用的Linux操作系统。

alt text

Linux 虚拟机安装

下面介绍两种Liunx虚拟机的安装方式

VMware上安装Liunx虚拟机

打开官网,点击DOWNLOAD FUSION OR WORKSTATION alt text 注册一个BORADOM账号 alt text 登录账号,点开左侧My Dashboard,搜索VMware Workstation Pro alt text 点开搜索结果,下滑找到Workstation Pro 17.5.2下载地址 alt text 点开后找到Personal Use (Windows),选择17.5.2版本 alt text 点击下载按钮获取软件包 alt text - Liunx桌面版镜像安装地址

alt text

打开安装好的VMware,左上角点击 文件-新建虚拟机 alt text 选择典型安装 alt text 输入系统名和密码 alt text 选择合适的存储位置 alt text 选择磁盘容量,最好不要少于64G alt text 点击下一步,完成安装,打开虚拟机 alt text 选择Minimal installtion,最小化安装系统,点击Continue进行下一步 alt text 选择Erase disk and install Ubuntu,清空虚拟磁盘的内容并安装Ubuntu,这一步清空的是分配给虚拟机的硬盘,而非虚拟机所在的硬盘(D:\等) alt text 输入虚拟机信息,选择自动登录,点击Continue完成安装 alt text 等待安装完成即可 alt text

使用WSL在windows上使用Liunx

首先设置Windows功能,打开适用于Linux的Windows子系统(即WSL)和虚拟机平台,安装完成后选择重启电脑。 alt text alt text 在微软商店中搜索Ubuntu 22.04.5 LTS并安装 alt text 打开Ubuntu,可能会报错0x800701bc alt text 打开Windows Powershell,设置WSL版本为WSL2并更新

wsl --set-default-version 2
wsl --update
alt text 再次打开Ubuntu,可能报错0x80370102,这是因为处理器并未打开虚拟化功能,可根据主板类型搜索对应的进入BIOS的教程,根据CPU类型开启 AMD SVM 或 Intel VT-x 功能 。 alt text 开启虚拟化功能后再次打开Ubuntu,发现成功启动,输入用户名和密码即可完成安装。 alt text 安装完成后,执行如下指令安装软件窗口所需的框架
sudo apt update
sudo apt install x11-apps
执行xeyesxclock测试,得到类似图中的窗口即可

alt text

如果安装了VS Code,则可安装WSL插件,然后点击左侧远程资源管理器链接到Linux系统中,这样就可以在VS Code中对WSL进行程序编写和调试等工作。

alt text alt text

Liunx命令基础

为什么要学习命令

早期的Linux没有图形化界面,一切操作都由命令完成。在长期发展中,Linux拥有了一套完整且优秀的命令行系统。仅仅使用命令就可以在Linux上实现绝大多数的操作

什么是Shell

Shell是包裹在操作系统外层的一道程序,负责外界与Linux内核的交互。 Shell接收用户或者其他应用程序的命令,然后将这些命令转化成内核能够理解的语言并传递给内核,内核执行命令完成后,再将执行结果返回给用户或者应用程序。 Shell就像是Linux内核的一个 “外壳”,所以 Shell(壳)的名称也由此而来。

常见的shell:

  • Windows:cmd、PowerShell
  • Linux:sh、bash、dash

可以使用ls -l /bin/sh查看系统使用的shell类型,Ubuntu中使用的一般是dash。

alt text

Shell 和 终端

终端是人机交互的接口,负责提供命令输入、输出环境。

Shell负责解析终端传入的数据,将其翻译后传递给内核,将内核的结果解析后传回终端。

启动终端后显示命令提示符:

  • root:用户名,root表示最高权限用户
  • @:分隔符
  • H……:主机名
  • ~/test:当前工作目录
  • #/$:身份提示符 超级用户/普通用户
  • (base):miniconda的base环境,非linux自带,负责管理python环境 alt text

目录操作

ls:列出目录内容

1
2
3
4
ls                             # 列出当前目录内容
ls -l/-lh        # 详细显示文件属性(以字节为单位显示大小 / 以B/KB/MB等为单位显示大小)
ls -a                          # 显示隐藏文件/文件夹
ls /path                       # 显示指定路径内容

cd:切换目录

1
2
3
cd                             # 切换到用户的主目录
cd /path                       # 切换到指定目录
cd ..                          # 返回上一级目录

pwd:显示当前目录路径

tree:以树状图列出目录,使用sudo apt install tree安装

文件和目录管理

cp:复制文件或目录

1
2
3
cp source.txt cpsource.txt     # 在当前目录复制文件并命名
cp -r /source/ /destination/   # 复制目录及其内容
cp -i source.txt destination   # 提示是否覆盖同名文件

mv:移动或重命名文件

mv oldname.txt newname.txt     # 重命名文件
mv /path/to/file /new/path/    # 移动文件

rm:删除文件或目录

1
2
3
4
5
rm file.txt                    # 删除文件
rm -r directory/               # 删除目录及其内容
rm -i file.txt                 # 删除前询问确认
rm -d directory/               # 删除空目录,同 rmdir dir/
rm -f file.txt                 # 强制删除文件

mkdir:创建目录

mkdir new_directory            # 创建单个目录
mkdir -p /parent/child/dir     # 创建多层级目录,若父目录不存在则创建

cat:查看文件

cat file.txt                   # 显示文件内容
cat file1.txt file2.txt        # 连接并显示多个文件内容

find:查找文件或目录

1
2
3
find /path -name "file.txt"    # 查找指定名称的文件
find /path -type f(普通文件)/d(目录)             # 查找指定类型的文件
find /path -size +100M         # 查找大于100MB的文件

其他常用指令

chmod:更改文件权限

echo:输出文本或变量内容

ping:测试网络连接

kill:结束进程

grep: 筛选含指定字符串的内容

Shell脚本编写

为什么学习Shell脚本

Windows专业版、Linux等常用系统都自带shell,执行shell脚本不需要安装额外的环境,具有很好的环境兼容性。

Shell脚本可以快速实现批量化处理任务。

管道和重定向

Linux有三个标准数据流:

  • stdin 标准输入
  • stdout 标准输出
  • stderr 标准错误输出

在Linux中,重定向允许将标准数据流导入指定位置。

输出重定向:> 覆盖写入文件,>> 追加写入文件。

输入重定向:< 从文件读取内容作为输入。

错误重定向:2> 将错误信息输出到文件。

同时重定向输出和错误:&> 将标准输出和错误同时写入文件。

管道:| 将一个命令的输出作为另一个命令的输入。

1
2
3
4
5
6
echo "Hello" > output.txt    # 覆盖写入
echo "World" >> output.txt   # 追加写入
sort < unsorted.txt          # 从 unsorted.txt 读取内容排序
ls /nonexistent 2> error.txt # 把错误信息保存到 error.txt
command &> all_output.txt    # 输出和错误都保存到 all_output.txt
cat file.txt | grep "error" | sort | uniq > error_log.txt

Shell语法

定义开头

#!/bin/bash
shell脚本的开头通过#!来声明脚本使用的shell类型,如果不声明则使用默认shell

输出函数echo

echo "hello world"

echo的两个参数:

  • -n: 不进行换行
  • -e: 解析反斜杠转义字符

变量

在Shell脚本中,变量没有严格的类型区分,所有变量默认都被视为字符串类型。当存储内容为数字时,变量也可以参与数学运算。

  • 定义变量

变量名=变量值

等号两边不可加空格

变量名只能包含字母、数字和下划线 。 变量名不能以数字开头。

只读变量在前加 readonly

  • 引用变量

$变量名

  • 清除变量值

unset 变量名

下面这个脚本展示了变量引用的特性

1
2
3
4
5
6
7
#!/bin/sh
num=10
echo "$num"
echo $num
echo $num 1 2 3
print="echo "$num""
$print
我们发现输出为
1
2
3
4
10
10
10 1 2 3
10
这就表明Shell的 $变量名 是直接对内容进行替换,这与C语言有较大不同。

C语言中printf("%d",n);的流程为printf函数读到%d,然后输出n存储的内容

Shell中echo "$num"的流程为先将$num替换为num对应的值10,指令变为echo "10"后再执行这个指令。因此Shell脚本的安全性很差,容易受到注入攻击。

特殊变量

1
2
3
4
5
6
7
$0:当前脚本的文件名。
$1, $2, …:传递给脚本或函数的参数。
$#:传递给脚本或函数的参数个数。
$@:传递给脚本或函数的所有参数。
$?:上个命令的退出状态。
$$:当前 Shell 进程的 PID。
$!:后台运行的最后一个进程的 PID。

数组

数组是bash特有的功能 sh和dash均不支持数组语法

在shell中使用括号表示数组

fruit=(apple banana cherry)

引用时和C语言类似,使用$数组名[索引]其中索引为@时表示输出整个数组

输入

使用read 变量名$1-9向脚本传递参数

算术操作符

运算类型 操作符 说明
算术运算 + 加法
- 减法
* 乘法
/ 除法
% 取余
++ 自增
-- 自减
关系运算 -eq 等于
-ne 不等于
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于
逻辑运算 && 逻辑与
\|\| 逻辑或
! 逻辑非
位运算 & 位与运算
\| 位或运算
^ 位异或运算
~ 位取反
<< 左移运算
>> 右移运算

if分支语法

if [ case1 ]
then
    command_1
elif [ case2 ]
then
    command_2
……
else
    command_n
fi

for循环语法

for var in a,b,c……
    do
        command
    done

for i in (a..b)
    do
        command
    done

#仅限bash
for ((initial_value; condition; increment))
    do
        command
    done

while循环和until循环

while是当满足条件时执行,until是执行到某个条件后结束

1
2
3
4
5
6
7
8
9
while [ condition ]
    do
        command
    done

until [ condition ]
    do
        command
    done

break

在循环中使用,跳出循环体。

continue

在循环中使用,跳过本次循环。

function

1
2
3
4
5
6
function fun() {
    commands
    ……
}

fun 参数1 参数2 ……
对于传入function的参数,通过$1-9在函数内使用

$?存储了最近一次函数返回的参数

或者使用$(fun 参数)获取函数返回值

获取命令输出

使用$(command)可以获取命令的输出

Shell脚本示例

解压文件夹下所有压缩包

#!/bin/bash

# 设置目标目录
TARGET_DIR="你的文件夹路径"

# 检查目标目录是否存在
if [ ! -d "$TARGET_DIR" ]; then
  echo "目录 $TARGET_DIR 不存在,请检查路径!"
  exit 1
fi

# 遍历目标目录中的文件
for file in "$TARGET_DIR"/*; do
  if [ -f "$file" ]; then
    case "$file" in
      *.zip) 
        # 解压 ZIP 文件
        echo "解压 ZIP 文件:$file"
        unzip -d "${file}_extracted" "$file" || echo "解压失败:$file"
        ;;
      *.tar) 
        # 解压 TAR 文件
        echo "解压 TAR 文件:$file"
        mkdir -p "${file}_extracted"
        tar -xf "$file" -C "${file}_extracted" || echo "解压失败:$file"
        ;;
      *.tar.gz | *.tgz) 
        # 解压 TAR.GZ 文件
        echo "解压 TAR.GZ 文件:$file"
        mkdir -p "${file}_extracted"
        tar -xzf "$file" -C "${file}_extracted" || echo "解压失败:$file"
        ;;
      *.tar.bz2) 
        # 解压 TAR.BZ2 文件
        echo "解压 TAR.BZ2 文件:$file"
        mkdir -p "${file}_extracted"
        tar -xjf "$file" -C "${file}_extracted" || echo "解压失败:$file"
        ;;
      *)
        # 跳过不支持的文件
        echo "跳过不支持的文件:$file"
        ;;
    esac
  fi
done

echo "解压完成!"

统计TXT文件行数

#!/bin/bash

# 定义目标目录和输出文件
TARGET_DIR="."
OUTPUT_FILE="line_counts.txt"

# 检查目标目录是否存在
if [ ! -d "$TARGET_DIR" ]; then
  echo "目录 $TARGET_DIR 不存在,请检查路径!"
  exit 1
fi

# 初始化输出文件
echo "文件行数统计结果:" > "$OUTPUT_FILE"

# 遍历目录中的所有 .txt 文件(排除 OUTPUT_FILE)
for file in "$TARGET_DIR"/*.txt; do
  if [ -f "$file" ] && [ "$file" != "$TARGET_DIR/$OUTPUT_FILE" ]; then
    # 使用 wc 命令统计行数并通过重定向追加结果到文件
    wc -l "$file" >> "$OUTPUT_FILE"
  fi
done

# 统计所有文件的总行数(显式排除 OUTPUT_FILE)
echo "总行数:" >> "$OUTPUT_FILE"
find "$TARGET_DIR" -maxdepth 1 -type f -name "*.txt" 
! -name "$(basename "$OUTPUT_FILE")" | xargs cat | wc -l >> "$OUTPUT_FILE"

# 提示用户结果已保存
echo "行数统计完成,结果保存在:$OUTPUT_FILE"