![Bash, форк с CLOEXEC](https://rvso.com/image/89171/Bash%2C%20%D1%84%D0%BE%D1%80%D0%BA%20%D1%81%20CLOEXEC.png)
Может ли Bash выполнить подпроцесс, не давая подпроцессу наследовать файловый дескриптор?
if flock -nx 9
then
# If begin program runs away, it will keep the lock.
begin program
else
echo "Lock held :/)" >&2
fi 9> /tmp/lk
решение1
Насколько я знаю, нет. Его нужно закрыть вручную:
if flock 9 -nx
then
program 9>&- #<= manual close of fd 9 after `program` has forked but before it execs
else
echo "Lock held :/)" >&2
fi 9> /tmp/lk
Если вы хотите чего-то похитрее, вы можете установить флаг, вызвав fcntl
функцию напрямую черезctypes.sh:
#!/bin/bash
echo initial
ls /proc/$$/fd/
echo with 9
{
ls /proc/$$/fd/
echo with 9 in an execced child
bash -c ' ls /proc/$$/fd/'
} 9</etc/passwd
echo
echo BEGIN MAGIC
FD_CLOEXEC=1
FD_SETFD=2
. ctypes.sh
echo initial
ls /proc/$$/fd/
echo with 9
{
dlcall fcntl int:9 int:$FD_SETFD int:$FD_CLOEXEC
ls /proc/$$/fd/
echo with 9 in an execced child
bash -c ' ls /proc/$$/fd/'
} 9</etc/passwd
Выход:
initial
0
1
2
255
with 9
0
1
2
255
9
with 9 in an execced child
0
1
2
3
9
BEGIN MAGIC
initial
0
1
2
255
with 9
0
1
2
255
9
with 9 in an execced child
0
1
2
3
(Это не опечатка при вставке — 9 действительно закрылась, когда дочерний bash был выполнен).
решение2
С помощью bash 5.0+ и примеров загружаемых модулей (debian также требует установки пакета bash-builtins
) вы можете использовать загружаемый модуль fdflags.
if flock -nx 9
then
enable -f /usr/lib/bash/fdflags fdflags
fdflags -s+cloexec 9
begin program
else
echo "Lock held :/)" >&2
fi 9> /tmp/lk