[Shell]文件描述符示例

本文详细介绍了Linux系统中Shell文件描述符的概念与使用方法,包括默认文件描述符、如何打开和复制文件描述符以及关闭它们的过程。此外还提供了一个实用脚本示例,展示如何根据不同的参数使用这些文件描述符。

  Linux系统中,每当进程打开一个文件时,系统就为其分配一个唯一的整型文件描述符,用来标识这个文件。大家知道,标C中,每个进程默认打开的有三个文件,标准输入、标准输出、标准错误输出,分别用一个FILE结构的指针来标示,即stdin、stdout、stderr,这三个结构中分别维护着三个文件描述符0、1、2。

打开文件描述符

  Shell中,0、1、2也是默认可用的三个文件描述符。为了利用其他文件描述符来标识特定文件,我们需要使用exec命令打开该文件,并指定一个数字作为描述符:

exec m> outfile 
exec n< infile

  第一行打开文件outfile,并赋予文件描述符m,第二行打开文件infile,并赋予文件描述符n。

复制文件描述符

  符号<&可以复制一个输入文件描述符,符号>&可以复制一个输出描述符。例如下面命令打开文件描述符n,并将其作为文件描述符m的副本:

exec n<&m
关闭文件描述符
exec n<&-
exec m<&-
一个演示脚本

  下面的这个脚本修改自《A Practical Guide to Linux Command, Editions, and Shell Programming》。不提供参数时,它将标准输入输出到标准输出;提供一个文件名参数时,将该文件输出到标准输出;提供两个文件名参数时,它将提一个文件复制到第二个文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#! /bin/sh
 
case $# in
    0)
        exec 3<&0 4>&1
        ;;
    1)
        exec 3<$1 4>&1
        ;;
    2)
        exec 3<$1 4>$2
        ;;
    *)
        echo "Usage: `basename $0` [source [dest]]"
        exit 1
        ;;
esac
cat <&3 >&4
exec 3<&- 4<&-
exit 0
Tags: shell.
你好!除了代码,此处没有多少原创之物,皆为本人搜集、整理、总结之记录与心得,欢迎转载分享!转载时请尽量注明出处,将不胜感激。祝你健康、快乐!
### 文件描述符在不同 Shell 脚本中的共享与冲突 #### 1. 文件描述符是否在不同脚本间共享 文件描述符在不同的 Shell 脚本之间通常不会直接共享[^3]。每个 Shell 进程拥有独立的文件描述符表,这意味着一个脚本中创建的文件描述符不会自动被另一个脚本继承或访问。然而,当使用某些特定的方式调用脚本时,文件描述符可能会被传递到子进程中。 例如,通过 `source` 或 `.` 命令调用脚本时,父脚本和子脚本运行在同一 Shell 进程中,因此文件描述符会被共享[^3]。而在通过 `exec` 或直接运行新脚本时,虽然子进程会继承父进程的文件描述符,但这些文件描述符是副本,父进程和子进程之间的文件描述符实际上是隔离的[^4]。 #### 2. 文件描述符是否会引发冲突 尽管文件描述符在不同 Shell 脚本中通常是隔离的,但在以下情况下可能会引发冲突: - **文件描述符继承**:如果一个脚本通过 `exec` 或其他方式启动了另一个程序,并且未关闭不需要的文件描述符,则子进程可能会意外地继承这些文件描述符,从而导致冲突。 - **锁机制冲突**:当多个脚本对同一个文件使用 `flock` 或其他锁机制时,如果未正确处理锁的获取和释放,可能会导致死锁或竞争条件[^1]。 - **全局文件描述符使用**:如果多个脚本同时操作标准输入、输出或错误输出(文件描述符 0、1 和 2),则可能会出现数据混杂或覆盖的情况[^3]。 #### 3. 如何避免冲突 为了避免文件描述符在不同脚本间的冲突,可以采取以下措施: - **明确关闭不需要的文件描述符**:在调用子进程之前,确保关闭父进程中不需要的文件描述符。例如: ```bash exec 3>&- # 关闭文件描述符 3 ``` - **使用局部作用域**:将文件描述符的操作限制在子 shell 或函数中,以减少对外部环境的影响。例如: ```bash ( exec 3>file.txt echo "Data" >&3 ) ``` - **避免文件描述符重叠**:为每个文件分配唯一的文件描述符,避免与其他脚本或进程使用的文件描述符发生冲突[^4]。 - **正确管理锁**:在使用 `flock` 时,确保锁的获取和释放逻辑清晰,并设置合理的超时时间以防止死锁[^1]。 #### 示例代码 以下是一个示例,展示如何在不同脚本间安全地使用文件描述符: ```bash # 父脚本 #!/bin/bash # 打开文件并分配文件描述符 3 exec 3>output.txt # 调用子脚本并传递文件描述符 ./child_script.sh 3>&3 # 关闭文件描述符 exec 3>&- ``` ```bash # 子脚本 #!/bin/bash # 使用从父脚本继承的文件描述符 echo "This is from child script" >&3 ``` ### 总结 文件描述符在不同 Shell 脚本中通常是隔离的,但在某些情况下可能会被继承或共享,从而引发冲突。通过明确关闭不需要的文件描述符、使用局部作用域、避免文件描述符重叠以及正确管理锁,可以有效避免这些问题[^3]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值