Bash スクリプトは、Apache で実行する場合と www-data で手動で実行する場合とは異なる動作をします。なぜですか?

Bash スクリプトは、Apache で実行する場合と www-data で手動で実行する場合とは異なる動作をします。なぜですか?

以下には、いくつかのファイルシステムのメンテナンスを試みるテストスクリプトがあります。これは単なる単純な部分です。 LVM論理ボリューム(マウント済み)をアンマウントして/dataデバイスで実行します。e2fsckスクリプトはApacheを介してリモートで実行する必要があります。

問題は、リモートでログインしてユーザーとして手動で実行するとスクリプトが機能します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

これがまさに私が期待したものです。ナビゲーションを通じてWeb上で実行できます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

関連情報