如何使用 ctypes、mount 和 umount 挂载和卸载 Linux 文件系统

问题描述 投票:0回答:1

我有一个 python 脚本(以 root 身份运行),需要能够挂载和卸载 USB 闪存驱动器的文件系统。我做了一些研究,我找到了这个答案https://stackoverflow.com/a/29156997,它使用ctypes。然而。答案仅指定如何安装,因此我尝试创建一个类似的函数来卸载设备。总而言之,我有这个:

import os
import ctypes
def mount(source, target, fs, options=''):
    ret = ctypes.CDLL('libc.so.6', use_errno=True).mount(source, target, fs, 0, options)
    if ret < 0:
        errno = ctypes.get_errno()
        raise RuntimeError("Error mounting {} ({}) on {} with options '{}': {}".
                           format(source, fs, target, options, os.strerror(errno)))

def unmount(device, options=0):
    ret = ctypes.CDLL('libc.so.6', use_errno=True).umount2(device, options)
    if ret < 0:
        errno = ctypes.get_errno()
        raise RuntimeError("Error umounting {} with options '{}': {}".format(device, options, os.strerror(errno)))

但是,尝试使用选项“0”或“1”执行卸载命令,例如:

unmount('/dev/sdb', 0)

unmount('/dev/sdb', 1)

给出以下错误:

Traceback (most recent call last):
  File "./BuildAndInstallXSystem.py", line 265, in <module>
    prepare_root_device()
  File "./BuildAndInstallXSystem.py", line 159, in prepare_root_device
    unmount('/dev/sdb', 0)
  File "./BuildAndInstallXSystem.py", line 137, in unmount
    raise RuntimeError("Error umounting {} with options '{}': {}".format(device, options, os.strerror(errno)))
RuntimeError: Error umounting /dev/sdb with options '0': Device or resource busy

以 2 作为选项运行它时:

unmount('/dev/sdb', 2)

卸载我的所有文件系统,包括“/”,导致系统崩溃。

即使我将设备号替换为特定分区,所有这些仍然适用:

/dev/sdb -> /dev/sdb1

我做错了什么?

python linux ctypes mount umount
1个回答
0
投票

您必须设置参数类型并对传递给 C 函数的值进行正确编码。多年来,您引用的问题已针对较新的 Python 版本进行了多次更新/改进。这是我仅使用

umount()
所做的工作(我认为您不需要在这个用例中使用
umount2()
):

import ctypes
import ctypes.util
import logging

log = logging.getLogger('whatever')

libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True)
libc.mount.argtypes = (ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_ulong, ctypes.c_char_p)
libc.umount.argtypes = [ctypes.c_char_p]

def mount(source, target, fs, options=''):
    ret = libc.mount(source.encode(), target.encode(), fs.encode(), 0, options.encode())
    if ret < 0:
        errno = ctypes.get_errno()
        msg = f'Error mounting {source} ({fs}) on {target} with options {options}: {os.strerror(errno)}'
        log.fatal(msg)
        raise OSError(errno, msg)


def umount(target):
    ret = libc.umount(target.encode())
    if ret < 0:
        errno = ctypes.get_errno()
        msg = f'Error unmounting {target}: {os.strerror(errno)}'
        log.fatal(msg)
        raise OSError(errno, msg)

关键是

target.encode()
。如果没有
encode()
,您将收到有关文件系统正忙的错误。

© www.soinside.com 2019 - 2024. All rights reserved.