我下面有一个测试脚本,尝试执行一些文件系统维护。这只是一个简单的片段;它卸载 LVM 逻辑卷(安装在),并在设备上/data
运行。e2fsck
该脚本必须通过 Apache 远程运行。
问题是,当我登录远程并以 user 身份手动运行该脚本时,该脚本www-data
可以工作,但当 Apache 运行它时,该脚本就不起作用。当 Apache 运行它时,脚本认为它已成功卸载/data
,但e2fsck
随后失败,因为它认为设备仍然繁忙。但是,测试fuser
不会显示任何内容,并且当脚本终止时设备仍处于安装状态。
我手动运行它如下:
root@vserver # su www-data -s /bin/bash
www-data@vserver $ cfg-test.sh
Status: 200 OK
Content-type: text/html
<p>Completed Ok.</p>
完成后,远程系统的状态如预期:/data
已卸载,系统日志包含:
Jan 23 15:51:26 vserver cfg-test.sh: Restarting as root
Jan 23 15:51:26 vserver cfg-test.sh: Unmounting /data...
Jan 23 15:51:27 vserver cfg-test.sh: Unmount succeeded; ll /data: (total 0)
Jan 23 15:51:27 vserver cfg-test.sh: e2fsck Ok
这正是我所期待的。我可以通过浏览到 来在网络上运行它https://vserver/cfg-test.sh
。然而,这是行不通的;浏览器报告Terminated with code 3. See the syslog for details.
系统日志显示:
Jan 23 15:48:49 vserver cfg-test.sh: Restarting as root
Jan 23 15:48:49 vserver cfg-test.sh: Unmounting /data...
Jan 23 15:48:49 vserver cfg-test.sh: Unmount succeeded; ll /data: (total 0)
Jan 23 15:48:49 vserver cfg-test.sh: fuser -c /dev/mapper/vg0-data: ()
Jan 23 15:48:49 vserver cfg-test.sh: e2fsck failed; terminating (/dev/mapper/vg0-data is in use.#012e2fsck: Cannot continue, aborting.) (/dev/mapper/vg0-data)
然而,他们umount
确实不是成功;/data
仍然安装在远程服务器上。为什么这个结果与手动运行脚本不同?如果相关的话,远程是 Ubuntu 22.04 VM。该脚本位于文件中,允许无需密码sudoers
即可运行。www-data
#!/bin/bash
scriptname=$(basename "$0")
dev=/dev/mapper/vg0-data
retcode=0
# log messages to syslog
log() {
if (($# < 1)); then
return
fi
msg="$1"
shift
while (($# > 0))
do
msg+=" ($1)"
shift
done
logger -t "$scriptname" "$msg"
}
if ((EUID > 0)); then
log "Restarting as root"
exec sudo "$0" "$@"
fi
while true ; do
log "Unmounting /data..."
output=$(umount -vvv --force /data 2>&1)
code=$?
if ((code > 0)); then
log "umount /data failed; terminating" "$code" "$output"
log "ll /data:" "$(ls -l /data)"
retcode=1
break
fi
# check mount's output
if output=$(mount | grep "$dev" 2>&1); then
log "/data is still mounted!" "$output"
log "ll /data:" "$(ls -l /data)"
retcode=2
break
fi
# exit codes 0 and 1 are both Ok
log "Unmount succeeded; ll /data:" "$(ls -l /data)"
output=$(e2fsck -p -f "$dev" 2>&1)
if (($? > 1)); then
log "fuser -c $dev:" "$(fuser -c $dev)"
log "e2fsck failed; terminating" "$output" "$dev"
retcode=3
break
fi
log "e2fsck Ok"
break
done
if ((retcode == 0)); then
echo "Status: 200 OK"
echo "Content-type: text/html"
echo ""
echo "<p>Completed Ok.</p>"
else
echo "Status: 400 Bad Request"
echo "Content-type: text/html"
echo ""
echo "<p>Terminated with code $retcode. See the syslog for details.</p>"
fi