Como ninguém escreveu uma resposta (apesar da generosidade), vou me explicar como resolvi isso finalmente.
O comentário demuru (muito obrigado!) estava certo e me trouxe no caminho certo: No Ubuntu 14.04, a inicialização do Apache é gerenciada por um script init sysv, e sendo um shell script Ele herda tudo (variáveis de ambiente, descritores de arquivos abertos, etc.), e o processo do apache iniciado por ele também herdará todos eles. O Mysql, por sua vez, é gerenciado pelo Upstart, o que garante um ambiente limpo para os serviços iniciados. Isso explica o comportamento diferente do Mysql e do Apache.
Armado com esse conhecimento, eu sabia melhor o que procurar e encontrei esta resposta em unix.stackexchange.com . Ele sugere fechar o descritor de arquivo no sub-shell que chama scripts que não devem herdá-lo, enquanto mantém o descritor aberto no shell externo, para garantir que o bloqueio permaneça efetivo.
Infelizmente, isso significa que eu tive que mover as chamadas de flock
para dentro do script de shell, caso contrário, meu script não saberia qual descritor de arquivo deve ser fechado. Então, meu novo shell script (que também se inspirou no este post no blog sobre flock
) tem a seguinte estrutura:
#!/bin/bash
FLOCK_FILE="/var/lock/backup-lock"
FLOCK_FD=20
# Locking
eval "exec $FLOCK_FD>'$FLOCK_FILE'"
if ! flock -n $FLOCK_FD
then
echo "FAILED! There is a backup script already running."
exit 1
fi
(
# Unlock in sub-shell, so daemons with bad startup scripts
# (like Apache) don't inherit the look.
# Note that the lock is still alive in general because it's
# held by the outer shell.
eval "exec $FLOCK_FD>-"
# ... normal backup stuff from the original script ...
# Among other stuff the mentioned vicious line:
service apache2 start
# ... normal backup stuff from the original script ...
)
# Unlock in outer shell because we're done.
eval "exec $FLOCK_FD>-"