जब मैं USB- डिवाइस में प्लग-इन करता हूं तो शेलस्क्रिप्ट को कैसे निष्पादित किया जाता है


28

जब मैं अपने लिनक्स मशीन में एक उपकरण में प्लग करता हूं, तो मैं एक स्क्रिप्ट निष्पादित करना चाहता हूं। उदाहरण के लिए, xinputएक निश्चित ड्राइव पर माउस या बैकअपस्क्रिप्ट पर चलाएं।

मैं सबसे हाल ही में इस पर लेख का एक बहुत कुछ देखा है, यहाँ और यहाँ । लेकिन मैं अभी काम नहीं कर सकता।

यहां कुछ सरल उदाहरण हैं जो कम से कम किसी प्रकार की प्रतिक्रिया प्राप्त करने की कोशिश कर रहे हैं।

/etc/udev/rules.d/test.rules

#KERNEL=="sd*", ATTRS{vendor}=="*", ATTRS{model}=="*", ATTRS{serial}=="*", RUN+="/usr/local/bin/test.sh"
#KERNEL=="sd*", ACTION=="add", "SUBSYSTEM=="usb", ATTRS{model}=="My Book 1140    ", ATTRS{serial}=="0841752394756103457194857249", RUN+="/usr/local/bin/test.sh"
#ACTION=="add", "SUBSYSTEM=="usb", RUN+="/usr/local/bin/test.sh"
#KERNEL=="sd*", ACTION=={add}, RUN+="/usr/local/bin/test.sh"
KERNEL=="sd*", RUN+="/usr/local/bin/test.sh"
KERNEL=="*", RUN+="/usr/local/bin/test.sh"

/usr/local/bin/test.sh

#!/usr/bin/env bash
echo touched >> /var/log/test.log

if [ "${ACTION}" = "add" ] && [ -f "${DEVICE}" ]
then
    echo ${DEVICE} >> /var/log/test.log
fi

नियम फ़ोल्डर द्वारा देखा जाता है inotifyऔर तुरंत सक्रिय होना चाहिए। मैं अपने कीबोर्ड, माउस, टैबलेट, मेमोरीस्टिक और यूएसबी-ड्राइव की भरपाई करता रहता हूं, लेकिन कुछ भी नहीं। कोई लॉग फ़ाइल नहीं छुआ।

अब, कम से कम यह जानने का सबसे सरल तरीका क्या होगा कि कुछ काम कर रहा है? किसी ऐसी चीज़ से काम करना आसान है जो किसी ऐसी चीज़ से काम कर रही है जो नहीं है।


1
क्या आपका यूनिक्स और लिनक्स पर पोस्ट करने का मतलब नहीं था ? आपका कर्नेल संस्करण क्या है? क्या आपने udevadm triggerनया नियम लागू करने के लिए एक उपकरण चलाया या प्लग किया?
गिलेस एसओ- बुराई को रोकना '

हां, मैं ऐसा करता हूं कि नियमों के प्रत्येक संपादन के बाद उन्हें आज़माने के लिए। मैंने तदनुसार प्रश्न संपादित किया। इस तरह से udv कुछ समय के लिए काम करता है, लेकिन मैं भाग रहा हूं 3.5.0-23-generic
Redsandro

जवाबों:


24

यदि आप किसी विशिष्ट डिवाइस पर स्क्रिप्ट चलाना चाहते हैं, तो आप विक्रेता और उत्पाद आईडी का उपयोग कर सकते हैं

  • इन /etc/udev/rules.d/test.rules:

    ATTRS{idVendor}=="152d", ATTRS{idProduct}=="2329", RUN+="/tmp/test.sh"
  • में test.sh:

    #! /bin/sh
    
    env >>/tmp/test.log
    file "/sys${DEVPATH}" >>/tmp/test.log
    
    if [ "${ACTION}" = add -a -d "/sys${DEVPATH}" ]; then
    echo "add ${DEVPATH}" >>/tmp/test.log
    fi

इसके साथ env, आप देख सकते हैं कि udev से पर्यावरण किसके साथ सेट है file, आप फ़ाइल प्रकार की खोज करेंगे।

आपके डिवाइस के लिए ठोस विशेषताओं के साथ खोज की जा सकती है lsusb

lsusb

देता है

...
बस 001 डिवाइस 016: आईडी 152 डी: 2329 JMicron Technology Corp. / JMicron USA Technology Corp. JM20329 SATA Bridge
...


1
यह दिलचस्प है! ऐसा लगता है कि इसे लिखने / लॉग / करने की अनुमति नहीं है। यह करता है करने के लिए / tmp / लिखने। मुझे लगता है कि इसे मेरे पिछले परीक्षणों को पढ़ने की कोई अनुमति नहीं थी।
Redsandro

@ रोदसंद्रो यह जानबूझकर नहीं था, बस, अच्छी तरह से, परीक्षण के उद्देश्य। वैसे भी, मुझे खुशी है कि इसने मदद की। ;-)
ओलाफ़ डायसेट

मैं आपको इस प्रश्न की जाँच करने और यह देखने के लिए प्रोत्साहित करना चाहूँगा कि क्या आपका ज्ञान वहाँ मूल्यवान हो सकता है। :)
रेड्संड्रो

3
आप ACTION=="add",सीधे नियम की परिभाषा में भी जोड़ सकते हैं ।
15:19 बजे अविन्द्र गोलचारण

4

यह सीधे आपके प्रश्न के बारे में नहीं है, लेकिन आप क्या कर रहे हैं इसके बारे में। यदि आप udev से एक बैकअप स्क्रिप्ट शुरू करते हैं तो आपको दो मुख्य मुद्दों का सामना करना पड़ेगा:

  1. डिवाइस तैयार होने से पहले आपकी जांच शुरू की जा सकती है और इसे माउंट किया जा सकता है, यदि आपको माउंट करने के लिए / देव नोड का उपयोग करना है तो आपको KERNEL == "sd *" स्थिति रखनी होगी।
  2. अधिक महत्वपूर्ण है, यदि आपके परिमार्जन को निष्पादित करने में कुछ समय लगता है (जो कि बैकअप स्क्रिप्ट के मामले में आसानी से हो सकता है) इसे शुरू होने के तुरंत बाद मार दिया जाएगा (लगभग 5 s)
  3. आपको कई जटिल उपयोगकर्ता अनुमति मुद्दों का सामना करना पड़ेगा

मेरी सलाह है कि अपने उपयोगकर्ता के घर में एक स्क्रिप्ट बनाएं जो एक नामित पाइप को सुनें और जिसे अतुल्यकालिक रूप से शुरू किया जाएगा:

#!/bin/bash

PIPE="/tmp/IomegaUsbPipe"
REMOTE_PATH="/path/to/mount/point"
LOCAL_PATH="/local/path/"


doSynchronization()
{
  #your backup here
}

trap "rm -f $PIPE" EXIT

#If the pipe doesn't exists, create it
if [[ ! -p $PIPE ]]; then
    mkfifo $PIPE
fi

#If the disk is already plugged on startup, do a syn
if [[ -e "$REMOTE_PATH" ]]
then
    doSynchronization
fi

#Make the permanent loop to watch the usb connection
while true
do
    if read line <$PIPE; then
        #Test the message red from the fifo
        if [[ "$line" == "connected" ]]
        then
            #The usb has been plugged, wait for disk to be mounted by KDE
            while [[ ! -e "$REMOTE_PATH" ]]
            do
                sleep 1
            done
            doSynchronization
        else
            echo "Unhandled message frome fifo : [$line]"
        fi
    fi
done
echo "Reader exiting"

नोट: मैं kde के साथ ऑटो-माउंट का उपयोग करता हूं इसलिए मैं प्रकट होने के लिए फ़ोल्डर की जांच करता हूं। आप udv के नियम से / में देव / sd * पैरामीटर पास कर सकते हैं और इसे स्क्रिप्ट में स्वयं माउंट कर सकते हैं। पंद्रह में लिखने के लिए यह मत भूलो कि udv एक खोल नहीं है और यह पुनर्निर्देशन काम नहीं करता है। आपका RUN ऐसा होना चाहिए:

RUN + = "/ बिन / श-सी '/ बिन / गूंज जुड़ा हुआ >> / tmp / IomegaUsbbipe"


यहां नामित पाइपों का बहुत उपयोग किया जाता है। मैं सोच रहा था कि आप भी tmp में एक मनमानी फ़ाइल बना सकते हैं और एक नामांकित पाइप के बजाय इसे देख सकते हैं, सही है?
jamescampbell

1

मैंने /ubuntu//a/516336 पर एक समाधान पोस्ट किया है और मैं यहाँ पर समाधान को कॉपी-पेस्ट भी कर रहा हूँ।

मैंने पियूडव का उपयोग करते हुए एक पायथन स्क्रिप्ट लिखी जिसे मैंने पृष्ठभूमि में चलाना छोड़ दिया। वह स्क्रिप्ट udev घटनाओं को सुनता है (इस प्रकार, यह बहुत कुशल है) और मुझे जो भी कोड चाहिए वह चलता है। मेरे मामले में, यह xinputमेरे डिवाइस को सेटअप करने के लिए कमांड चलाता है ( सबसे हालिया संस्करण के लिए लिंक )।

यहाँ एक ही स्क्रिप्ट का एक छोटा संस्करण है:

#!/usr/bin/env python3

import pyudev
import subprocess

def main():
    context = pyudev.Context()
    monitor = pyudev.Monitor.from_netlink(context)
    monitor.filter_by(subsystem='usb')
    monitor.start()

    for device in iter(monitor.poll, None):
        # I can add more logic here, to run different scripts for different devices.
        subprocess.call(['/home/foo/foobar.sh', '--foo', '--bar'])

if __name__ == '__main__':
    main()

1
एक अच्छी स्क्रिप्ट लगती है, +1। एक चीज जो मैं सुझाऊंगा वह सिर्फ एक स्ट्रिंग के बजाय सूची का उपयोग करना है call()। इस तरह यदि foobar.shस्क्रिप्ट को तर्क प्रदान करना आवश्यक है , तो आप इसे गतिशील रूप से कर सकते हैं।
सर्गी कोलोडियाज़नी

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

-1

जब बूट डिवाइस डाला जाता है तो बूट पर स्क्रिप्ट चलाने के लिए मैं नीचे दिए गए समाधान का उपयोग करता हूं:

पेनड्राइव या किसी अन्य यूएसबी स्टोरेज को फॉर्मेट करें और ऐसा करते समय एक नाम दें। फिर /etc/rc.local ऐड लाइन मेंls -q /dev/disk/by-label > /home/pi/label.txt

यह एक txt फ़ाइल बनाएगा, जिसे लेबल कहा जाता है। Txt (कोई अन्य नाम हो सकता है)

फिर /etc/rc.local में फिर से एक और 2 लाइनें जोड़ें:

if  grep -q USB_drive_name /home/pi/label.txt; then
sudo /home/pi/script.sh

अब हर नाम के साथ USB_drive_name डाला जाता है, यह स्क्रिप्ट चलाएगा।

समाधान के ऊपर कुछ कम संशोधनों के साथ उपयोग किया जा सकता है जब सिस्टम ऊपर और चल रहा है।


प्रश्न का उत्तर नहीं देता है: यह केवल बूट-टाइम को कवर करता है (और udevअन्य समय के लिए उपयोग करना "कुछ कम संशोधन" नहीं हैं) और रास्पबेरी पाई। एक अनावश्यक है sudo- rc.localजड़ के रूप में चलता है, यह एक विशेषाधिकार वृद्धि मुद्दा है - एक फाइल जो एक सामान्य उपयोगकर्ता द्वारा संपादन योग्य है, उसे रूट पर चलाया जाता है।
गर्ट वैन डेन बर्ग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.