在Bash脚本中怎么关闭文件描述符?

本文介绍如何在Bash脚本中关闭由A进程通过system()函数启动并打开的文件描述符,以解决资源泄露问题。

在写一个Bash脚本的时候碰到一个问题,这个脚本是用来启动一个程序B的,而这个脚本又被另一个程序A调用,结果发现新启动的B进程中有很多A进 程打开的文件描述符(如Socket)。因此决定在脚本中将它们关闭,因为为了简单起见,我在A程序中使用了system()来启动该脚本。增加了关闭文 件描述符的脚本如下:

#!/bin/sh

cd $(dirname "$0") || exit 1

exec 3>&-
exec 4>&-



./rbtunnel "$@" &

#sleep 1


这里的关键点就是关闭文件描述的代码:exec fd>&-   也可以是:exec fd<&-  其中fd为文件描述符的数字,而文件描述符在Linux下可以通过lsof -c rbtunnel来查看。

 

  源文:http://www.vktone.com/articles/how-to-close-file-descriptor-on-bash.html

 

### 文件描述符在不同 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]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值