1

I have a test script below which attempts to carry out some filesystem maintenance. This is just a simple fragment; it unmounts an LVM logical volume (mounted at /data), and runs e2fsck on the device. The script has to be run remotely, via Apache.

The problem is that the script works when I log into the remote and run it manually as user www-data, but it doesn't work when Apache runs it. When Apache runs it, the script thinks that it has successfully unmounted /data, but e2fsck then fails because it thinks the device is still busy. However, a test with fuser doesn't show anything, and the device is still mounted when the script terminates.

I run it manually as follows:

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>

On completion, the state of the remote system is as expected: /data is unmounted, and the syslog contains:

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

This is exactly what I'm expecting. I can instead run this over the web by browsing to https://vserver/cfg-test.sh. However, this doesn't work; the browser reports Terminated with code 3. See the syslog for details. The syslog shows:

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)

However, the umount did not succeed; /data is still mounted on the remote server. Why is this result different from a manual run of the script? The remote is a Ubuntu 22.04 VM, if it's relevant. The script is in the sudoers file to allow it to be run by www-data without a password.


#!/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
9
  • 1
    Does /data actually live at /dev/mapper/vg0-data?
    – eyoung100
    Jan 23 at 17:08
  • @eyoung100: yes, it does: df -h shows /dev/mapper/vg0-data 90M 132K 83M 1% /data. I only use /data explicitly in the script because the directory name is preferred for umount.
    – EML
    Jan 23 at 17:35
  • And what happens when you run the script manually pointing it at the same location? I.e. try su www-data && umount /dev/mapper/vg0-data and report back. We want to see if the command succeeds outside of the script to see if the command has issues or the script
    – eyoung100
    Jan 23 at 17:41
  • Umm... don't think I can run that as a one-liner? I just get 'This account is currently not available'
    – EML
    Jan 23 at 17:45
  • 2
    It's very dangerous what you're doing there.
    – annahri
    Jan 23 at 23:14

0

You must log in to answer this question.

Browse other questions tagged .