आटोमेटिक USB ड्राइव को सिस्टमड के साथ


27

हम अपने सर्वर को आधुनिक डेबियन जेसी आधारित प्रणाली के लिए बहुत ही आउट-ऑफ-डेट डिस्ट्रो से अपडेट कर रहे हैं, जिसमें lightdm / xfce और पाठ्यक्रम systemd (और udisks2) शामिल हैं। एक स्टिकिंग पॉइंट USB ड्राइव को स्वचालित कर रहा है। हम कुछ udv नियमों के साथ इसे पूरा करते थे। पुराने नियम लगभग अभी भी काम करते हैं - माउंट पॉइंट बन जाता है और ड्राइव ठीक हो जाता है, लेकिन कुछ सेकंड के बाद systemd कुछ ऐसा कर रहा है जो माउंट को तोड़ता है, इसलिए बाद के एक्सेस प्रयासों के परिणामस्वरूप "ट्रांसपोर्ट एंडपॉइंट जुड़ा नहीं है" त्रुटियां।

कमांड लाइन के माध्यम से ड्राइव को मैन्युअल रूप से माउंट करना ठीक काम करता है। तो एक फ़ाइल प्रबंधक (थूनर और थूनर-वोल्मैन को देता है, जो बदले में udisks2 का उपयोग करता है)। लेकिन वे व्यवहार्य विकल्प नहीं हैं - ये सिस्टम ज्यादातर बिना सिर के चलते हैं, इसलिए थूनर सामान्य रूप से नहीं चल रहा है। हमें अनअटेंडेड क्रोन-आधारित बैकअप के लिए डिस्क ड्राइव में प्लग करने में सक्षम होना चाहिए।

मैंने सोचा था कि एक अलग काम करने के लिए udv स्क्रिप्ट को संशोधित करना, जो माउंट करने से पहले कुछ सेकंड इंतजार करता है, हो सकता है कि चाल चलें, लेकिन सिस्टमड इसे रोकने के लिए अपने रास्ते से बाहर जाने लगता है - यह किसी भी तरह से अभी भी खत्म करने के लिए अलग नौकरी का इंतजार करता है जारी है।

शायद udev स्क्रिप्ट गुदगुदी udisks2 किसी भी तरह सही दृष्टिकोण है? मैं एक हार में हूं, इसलिए किसी भी सलाह की बहुत सराहना की।


1
केवल tangentially संबंधित, लेकिन ... आप एक सर्वर पर xfce डाल रहे हैं?
पार्थियन ने मार

आह, मैंने "सर्वर" शब्द का उपयोग शिथिल किया है ... सिस्टम के साथ सभी उपयोगकर्ता इंटरैक्शन एक वेब ऐप के माध्यम से होता है, जो आमतौर पर नेटवर्क पर एक ब्राउज़र के माध्यम से एक्सेस किया जाता है। लेकिन कुछ ग्राहक एक गैर-नेटवर्क समाधान पसंद करते हैं, इसलिए हम कंसोल पर एक प्रकार के कियोस्क मोड में चलाते हैं। (यह नेटवर्क कॉन्फिग डिबगिंग के लिए भी उपयोगी है, आप मॉनिटर / माउस / कीबोर्ड में प्लग इन कर सकते हैं और लिनक्स लॉगिन क्रेडेंशियल्स की आवश्यकता के बिना वेब ऐप में बुनियादी नैदानिक ​​उपकरण एक्सेस कर सकते हैं)। वहाँ शायद lightdm / xfce की तुलना में एक हल्का वजन समाधान है, लेकिन यह स्थापित करने के लिए सबसे सरल था ...
माइक ब्लैकवेल

सीधे तौर पर स्क्रिप्ट चलाने वाले सिस्टमड-यूडव्ड नियमों के इच्छुक किसी के लिए: मेरे पास यह था; इसने थोड़ी देर के लिए काम किया, लेकिन कुछ बिंदु पर स्क्रिप्ट चलाना बंद हो गया अगर udvd को स्वचालित रूप से शुरू किया गया था। कमांड लाइन से रोकें और पुनः आरंभ करें, और यह ठीक रहेगा। उसके शीर्ष पर, इसने NTFS + FUSE के साथ कभी अच्छा काम नहीं किया क्योंकि udv ने पाया कि इसमें एक लंबे समय से चल रहे बच्चे की प्रक्रिया (ntfs-3G) थी और इसे 60 के दशक के बाद मार दिया गया। निचला रेखा: udev नियम सीधे एक स्क्रिप्ट चलाने से समय की बर्बादी है। उत्तर में उल्लिखित नियमों के बजाय udv नियमों और एक systemd सेवा के साथ जाएं। फिर आपको नामस्थान (माउंटफ्लैग्स = दास) से भी निपटने की जरूरत नहीं है।
मार्क

मेरे पास एक स्क्रिप्ट का एक समान मुद्दा था जो udv द्वारा शुरू किया गया था जो नेटवर्क कनेक्शन बनाने में सक्षम नहीं था। सिस्टमड का उपयोग करने के नीचे के समाधान ने इसके लिए भी काम किया - धन्यवाद!
क्वेंटिन स्टैफ़ोर्ड-फ्रेजर

जवाबों:


28

कई झूठी शुरुआत के बाद मैंने यह पता लगाया। कुंजी udev और एक बढ़ते स्क्रिप्ट के बीच एक systemd इकाई सेवा को जोड़ने के लिए है।

(रिकॉर्ड के लिए, मैं udisks2 (जैसे कुछ के माध्यम से udisksctl mount -b /dev/sdb1) का उपयोग करके इस काम को प्राप्त करने में सक्षम नहीं था, जिसे या तो सीधे एक udv नियम से या एक सिस्टम यूनिट फ़ाइल से कहा जाता है। एक दौड़ की स्थिति प्रतीत होती है और डिवाइस नोड काफी तैयार नहीं है। , जिसके परिणामस्वरूप, Error looking up object for device /dev/sdb1दुर्भाग्यपूर्ण है, क्योंकि udisks2 सभी आरोह बिंदु गड़बड़ का ख्याल रख सकता है ...)

भारी उठाने का कार्य एक शेल स्क्रिप्ट द्वारा किया जाता है, जो माउंट पॉइंट्स को बनाने और निकालने का ध्यान रखता है, और ड्राइव को माउंट और अनमाउंट करता है।

/usr/local/bin/usb-mount.sh

#!/bin/bash

# This script is called from our systemd unit file to mount or unmount
# a USB drive.

usage()
{
    echo "Usage: $0 {add|remove} device_name (e.g. sdb1)"
    exit 1
}

if [[ $# -ne 2 ]]; then
    usage
fi

ACTION=$1
DEVBASE=$2
DEVICE="/dev/${DEVBASE}"

# See if this drive is already mounted, and if so where
MOUNT_POINT=$(/bin/mount | /bin/grep ${DEVICE} | /usr/bin/awk '{ print $3 }')

do_mount()
{
    if [[ -n ${MOUNT_POINT} ]]; then
        echo "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}"
        exit 1
    fi

    # Get info for this drive: $ID_FS_LABEL, $ID_FS_UUID, and $ID_FS_TYPE
    eval $(/sbin/blkid -o udev ${DEVICE})

    # Figure out a mount point to use
    LABEL=${ID_FS_LABEL}
    if [[ -z "${LABEL}" ]]; then
        LABEL=${DEVBASE}
    elif /bin/grep -q " /media/${LABEL} " /etc/mtab; then
        # Already in use, make a unique one
        LABEL+="-${DEVBASE}"
    fi
    MOUNT_POINT="/media/${LABEL}"

    echo "Mount point: ${MOUNT_POINT}"

    /bin/mkdir -p ${MOUNT_POINT}

    # Global mount options
    OPTS="rw,relatime"

    # File system type specific mount options
    if [[ ${ID_FS_TYPE} == "vfat" ]]; then
        OPTS+=",users,gid=100,umask=000,shortname=mixed,utf8=1,flush"
    fi

    if ! /bin/mount -o ${OPTS} ${DEVICE} ${MOUNT_POINT}; then
        echo "Error mounting ${DEVICE} (status = $?)"
        /bin/rmdir ${MOUNT_POINT}
        exit 1
    fi

    echo "**** Mounted ${DEVICE} at ${MOUNT_POINT} ****"
}

do_unmount()
{
    if [[ -z ${MOUNT_POINT} ]]; then
        echo "Warning: ${DEVICE} is not mounted"
    else
        /bin/umount -l ${DEVICE}
        echo "**** Unmounted ${DEVICE}"
    fi

    # Delete all empty dirs in /media that aren't being used as mount
    # points. This is kind of overkill, but if the drive was unmounted
    # prior to removal we no longer know its mount point, and we don't
    # want to leave it orphaned...
    for f in /media/* ; do
        if [[ -n $(/usr/bin/find "$f" -maxdepth 0 -type d -empty) ]]; then
            if ! /bin/grep -q " $f " /etc/mtab; then
                echo "**** Removing mount point $f"
                /bin/rmdir "$f"
            fi
        fi
    done
}

case "${ACTION}" in
    add)
        do_mount
        ;;
    remove)
        do_unmount
        ;;
    *)
        usage
        ;;
esac

स्क्रिप्ट, बदले में, एक systemd इकाई फ़ाइल द्वारा कहा जाता है। हम "@" फ़ाइल नाम सिंटैक्स का उपयोग करते हैं ताकि हम डिवाइस नाम को एक तर्क के रूप में पारित कर सकें।

/etc/systemd/system/usb-mount@.service

[Unit]
Description=Mount USB Drive on %i
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/local/bin/usb-mount.sh add %i
ExecStop=/usr/local/bin/usb-mount.sh remove %i

अंत में, कुछ udv नियम हॉटप्लग / अनप्लग पर सिस्टमड यूनिट सेवा को शुरू और बंद करते हैं:

/etc/udev/rules.d/99-local.rules

KERNEL=="sd[a-z][0-9]", SUBSYSTEMS=="usb", ACTION=="add", RUN+="/bin/systemctl start usb-mount@%k.service"

KERNEL=="sd[a-z][0-9]", SUBSYSTEMS=="usb", ACTION=="remove", RUN+="/bin/systemctl stop usb-mount@%k.service"

इस चाल को करने के लिए लगता है! सामान को डिबग करने के लिए कुछ उपयोगी कमांड इस प्रकार हैं:

  • udevadm control -l debugवर्बोज़ लॉगिंग चालू करता है /var/log/syslogताकि आप देख सकें कि क्या हो रहा है।
  • udevadm control --reload-rules नियमों में फाइल को संशोधित करने के बाद। dir (आवश्यक नहीं हो सकता है, लेकिन चोट नहीं पहुँचा सकता है ...)।
  • systemctl daemon-reload आपके द्वारा systemd इकाई फ़ाइलों को संशोधित करने के बाद।

4
वाह। यह कमाल का है। काश मैं कई upvotes दे सकता! केवल एक चीज मैं संशोधित करने के लिए किया था कि मेरे सिस्टम पर, blkidएक को निकालने के लिए प्रतीत नहीं होता है ID_FS_LABEL, तो मैं बस का इस्तेमाल किया DEVBASEबजाय LABELनिर्माण करने MOUNT_POINTके बजाय।
ट्रैविस ग्रिग्स

क्या इस सेटअप को ATA / SCSI उपकरणों के साथ काम करने के लिए संशोधित किया जा सकता है? देखें: serverfault.com/q/825779/297059
user339676

@ ट्राविस - के udevadmबजाय आप उपयोग कर सकते हैं blkid। यह बहुत अधिक विस्तार के साथ-साथ अतिरिक्त जानकारी भी देता है। (उदाहरण के लिए, udevadm info --query=property --name=sda1)
user339676

यह बूट पर अच्छी तरह से काम नहीं करता है, अगर एक USB डिवाइस पहले से जुड़ा हुआ है। कोई विचार?
मीकल आर्टाज़ोव

जब नलग्लब्स सेट नहीं होते हैं, तो अनमाउंट पर, क्लीनअप एक त्रुटि उत्पन्न कर सकता है /usr/bin/find: '/media/*': No such file or directory। क्लीनअप if [ "$f" != "/media/*" ]; thenचलाने से पहले एक अतिरिक्त चेक का उपयोग कर सकते हैं find
प्रो बैकअप

12

एक नया, रसीला systemdऑटो-माउंट विकल्प है जिसका उपयोग किया जा सकता है fstabजिसके साथ आप सभी मानकीकृत माउंट अनुमति विकल्पों का उपयोग कर सकते हैं, और यह इस तरह दिखता है:

  x-systemd.automount

एक fstabपंक्ति में इसका एक उदाहरण :

  /dev/sdd1   /mnt/hitachi-one     auto     noauto,x-systemd.automount     0 2

noautoविकल्प यह मतलब होगा, बूट पर स्थापित किया जा करने के लिए पुराने सॉफ्टवेयर के साथ के रूप में प्रयास नहीं करेंगे autofs

आपको एक नई x-systemd.automountलाइन जोड़ने के बाद fstabचलाने की आवश्यकता है:

  sudo systemctl daemon-reload

और फिर दोनों, या एक, निम्न में से:

  sudo systemctl restart remote-fs.target
  sudo systemctl restart local-fs.target

इसके बारे में अधिक जानकारी के लिए:

https://wiki.archlinux.org/index.php/Fstab#Automount_with_systemd


sudo systemctl restart local-fs.targetमेरे लिए चाल
चली

2

मैंने @MikeBackwell से स्क्रिप्ट को संशोधित किया है:

  • न केवल /dev/sd[a-z]लेकिन , कई वर्णों को पहचानने वाले डिवाइस नाम पहचानते हैं /dev/sd[a-z]*; अक्सर सर्वरों के मामले में बड़ी संख्या में स्पिंडल होते हैं।
  • स्वचालित ड्राइव की सूची को ट्रैक करें /var/log/usb-mount.track
  • /var/log/messagesटैग usb-mount.sh के साथ क्रियाओं को लॉग इन करें
  • माउंट बिंदु के लिए डिवाइस लेबल के साथ उपसर्ग डिवाइस का नाम ड्राइव के साथ समस्याओं में नहीं चलने के लिए जिसे लेबल (खाली) नहीं सौंपा गया है /media/sdd2_usbtest, और;/media/sdd2_
  • यदि आवश्यक हो तो फ़ाइलों को उचित रूप से और पूर्ववत करने के लिए आवरण लिपियों को शामिल करें

चूँकि @MikeBlackwell ने पहले ही अधिकांश भारी उठाने का काम किया है, इसलिए मैंने इसे फिर से लिखने के लिए नहीं चुना; बस आवश्यक परिवर्तन किए हैं। मैंने उनके काम को उनके नाम और मूल उत्तर के यूआरआई को देखते हुए स्वीकार किया है।

इसे https://github.com/raamsri/automount-usb पर पाएं


2

Pmount , systemd और माइक ब्लैकवेल के दृष्टिकोण का उपयोग करके , आप पूरी बात को सरल बना सकते हैं:

/etc/systemd/system/usb-mount@.service

[Unit]
Description=Mount USB Drive on %i
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/bin/pmount --umask 000 /dev/%i /media/%i
ExecStop=/usr/bin/pumount /dev/%i

/etc/udev/rules.d/99-usb-mount.rules

ACTION=="add",KERNEL=="sd[a-z][0-9]*",SUBSYSTEMS=="usb",RUN+="/bin/systemctl start usb-mount@%k.service"
ACTION=="remove",KERNEL=="sd[a-z][0-9]*",SUBSYSTEMS=="usb",RUN+="/bin/systemctl stop usb-mount@%k.service"

HTH और धन्यवाद माइक।


0

मैं वॉरेन यंग के जवाब के साथ जाऊंगा, मेरे पास कुछ बदलाव हैं जो मैंने किए हैं

मैंने कुछ अंतरिक्ष सुरक्षा को जोड़ा क्योंकि यह ड्राइव के लिए पर्यावरण के निष्कासन से त्रुटियां दे रहा था।

मैंने एक usb डिस्क को chmod करने के लिए एक सेक्शन जोड़ा ताकि सभी यूजर्स की नॉन ntfs या vfat डिस्क तक पूरी पहुंच हो।

/usr/local/bin/usb-mount.sh

#!/bin/bash

# This script is called from our systemd unit file to mount or unmount
# a USB drive.

usage()
{
    echo "Usage: $0 {add|remove} device_name (e.g. sdb1)"
    exit 1
}

if [[ $# -ne 2 ]]; then
    usage
fi

ACTION="$1"
DEVBASE="$2"
DEVICE="/dev/${DEVBASE}"

# See if this drive is already mounted, and if so where
MOUNT_POINT=$(/bin/mount | /bin/grep ${DEVICE} | /usr/bin/awk '{ print $3 }')

do_mount()
{
    if [[ -n "${MOUNT_POINT}" ]]; then
        echo "Warning: ${DEVICE} is already mounted at ${MOUNT_POINT}"
        exit 1
    fi

    # Get info for this drive: $ID_FS_LABEL, $ID_FS_UUID, and $ID_FS_TYPE
    # added some sed's to avoid space issues
    eval $(/sbin/blkid -o udev ${DEVICE}|sed 's/=/="/'|sed 's/$/"/')

    # Figure out a mount point to use
    LABEL="${ID_FS_LABEL}"
    if [[ -z "${LABEL}" ]]; then
        LABEL="${DEVBASE}"
    elif /bin/grep -q " /media/${LABEL} " /etc/mtab; then
        # Already in use, make a unique one
        LABEL+="-${DEVBASE}"
    fi
    MOUNT_POINT="/media/${LABEL}"

    echo "Mount point: ${MOUNT_POINT}"

    /bin/mkdir -p "${MOUNT_POINT}"

    # Global mount options
    OPTS="rw,relatime"
    #added a chmod checker for file systems that don't 
    #understand allow all to read write
    CHMOD=no
    # File system type specific mount options
    if [[ ${ID_FS_TYPE} == "vfat" ]]; then
        OPTS+=",users,gid=100,umask=000,shortname=mixed,utf8=1,flush"
    #added options I wanted on ntfs
    elif [[ ${ID_FS_TYPE} == "ntfs" ]]; then
        OPTS+=",user,users,umask=000,allow_other"
    else
       CHMOD=yes
    fi

    if ! /bin/mount -o "${OPTS}" ${DEVICE} "${MOUNT_POINT}"; then
        echo "Error mounting ${DEVICE} (status = $?)"
        /bin/rmdir "${MOUNT_POINT}"
        exit 1
    fi


    echo "**** Mounted ${DEVICE} at ${MOUNT_POINT} ****"
    if [ "${CHMOD}" = "yes" ];then
        /usr/bin/find "${MOUNT_POINT}" -type f -exec chmod 0666 {} \;
        /usr/bin/find "${MOUNT_POINT}" -type d -exec chmod 0777 {} \;
    fi
}

do_unmount()
{
    if [[ -z ${MOUNT_POINT} ]]; then
        echo "Warning: ${DEVICE} is not mounted"
    else
        /bin/umount -l ${DEVICE}
        echo "**** Unmounted ${DEVICE}"
    fi

    # Delete all empty dirs in /media that aren't being used as mount
    # points. This is kind of overkill, but if the drive was unmounted
    # prior to removal we no longer know its mount point, and we don't
    # want to leave it orphaned...
    for f in /media/* ; do
        if [[ -n $(/usr/bin/find "$f" -maxdepth 0 -type d -empty) ]]; then
            if ! /bin/grep -q " $f " /etc/mtab; then
                echo "**** Removing mount point $f"
                /bin/rmdir "$f"
            fi
        fi
    done
}

case "${ACTION}" in
    add)
        do_mount
        ;;
    remove)
        do_unmount
        ;;
    *)
        usage
        ;;
 esac

आप वर्णन करना चाहते हैं कि मूल उत्तर और आपके बीच कुछ शब्दों में क्या अलग है, इसे और अधिक उपयोगी बनाने के लिए। पुनश्च: वॉरेन यंग द्वारा कोई जवाब नहीं था; शायद आपका मतलब माइक ब्लैकवेल का उत्तर था जिसे संपादित किया गया था?
आमिर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.