如何使 movemail 在 SSHFS 文件系统上工作?

如何使 movemail 在 SSHFS 文件系统上工作?

我想避免设置 IMAP 服务器,而是使用 mailutilsmovemail结合SSHFS将一些邮件从外部主机移至本地计算机。不幸的是,它失败了:

$ sshfs -o noforget exthost:/ /mnt/sshfs
$ movemail /mnt/sshfs/var/mail/dirdi /home/user/dirdi/ext_mail
movemail: mailbox `/mnt/sshfs/var/mail/dirdi': cannot lock: Lock file check failed

但是,锁文件/var/mail/dirdi.lock实际上是在 exthost 上创建的。我查看了源代码并追踪错误,直到这里:http://git.savannah.gnu.org/cgit/mailutils.git/tree/libmailutils/base/locker.c?h=release-3.5#n120在我看来,stat_check函数内部的某些检查失败了,但我无法判断是哪一个以及为什么。

答案1

作为一种解决方法,我创建了一个在远程邮箱的本地副本上smovemail运行的 shell 脚本:movemail

#!/bin/bash

# initialize variables
status=0
src=
dest=
remotefs=
copy=
mountpoint=
lockfile=

# function to print errors
function error {
    echo "(E) ${1}" >&2
    status=1
}

# function to tear down created environment
function tear_down {

    # remove local copy of remote mailbox
    if [[ "${copy}" ]]; then
        rm -- "${copy}" ||
            error "Unable to remove local copy of remote mailbox '${copy}.'"
    fi

    # remove lockfile
    if [[ "${lockfile}" ]]; then
        rm -- "${lockfile}" ||
            error "Unable to remove lockfile '${lockfile}. Remote mailbox may still be locked.'"
    fi

    # unmount SSHFS
    mount | cut -d " " -f 3 | grep "${mountpoint}" >/dev/null &&
        fusermount -u "${mountpoint}" 2>/dev/null ||
            error "Unable to unmount remote filesystem mounted at '${mountpoint}'"

    # remove mountpoint
    if [[ "${mountpoint}" ]]; then
        rmdir "${mountpoint}" 2>/dev/null ||
            error "Unable to remove mountpoint '${mountpoint}'"
    fi

    exit ${status}
}

# register tear down function to run in any case
trap tear_down EXIT

# print usage
if [[ ${#} -ne 2 ]]; then
    error "Usage: $(basename ${0}) remote_mailbox local_mailbox"
    exit
fi
# TODO implement better parameter sanitization

# create mountpoint
mountpoint=$(mktemp -d 2>/dev/null) || {
    error "Unable to create mountpoint."
    exit
}

# determine locations
src="${mountpoint}/"$(basename "${1}" 2>/dev/null)
remotefs=$(dirname "${1}" 2>/dev/null)
dest="${2}"

# mount SSHFS
sshfs "${remotefs}" "${mountpoint}" -o workaround=rename,reconnect,uid=$(id -u),gid=$(id -g) >/dev/null 2>&1 || {
    error "Unable to mount remote filesystem '${remotefs}'"
    exit
}

# lock remote mailbox
lockfile=$(mktemp -p "${mountpoint}" 2>/dev/null) || {
    error "Unable to create lockfile"
    exit
}
mv -n "${lockfile}" "${src}.lock"
if [[ -f "${lockfile}" ]]; then
    error "Unable to lock mailbox."
    exit
fi
lockfile="${src}.lock"

# create local copy
copy=$(mktemp 2>/dev/null) || {
    error "Unable to create copy of remote mailbox."
    exit
}
cp "${src}" "${copy}" 2>/dev/null || {
    error "Unable to copy remote mailbox."
    exit
}

# run movemail
movemail "${copy}" "${dest}" || {
    error "Unable to move mails."
    exit
}

# play back copy
cp "${copy}" "${src}" 2>/dev/null || {
    error "Unable to play back local copy."
    exit
}

可以通过以下方式调用$ smovemail remoteuser@remotehost:/var/mail/remoteuser /var/mail/localuser

如果您想使用此脚本,请随意使用,但是请注意:此脚本利用命令mv -n来锁定远程邮箱,因此基于此命令的假设原子在 SSHFS 文件系统上。根据我的研究,这个假设并不总是成立!但是,我进行了一些测试,并没有让它崩溃,所以对我来说这已经足够好了。

非常欢迎对改进提出意见和建议。

相关内容