আমি যখন কোনও ইউএসবি-ডিভাইস প্লাগ ইন করি তখন কীভাবে শেলসক্রিপ্ট কার্যকর করা যায়


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নতুন নিয়ম প্রয়োগ করতে কোনও ডিভাইস চালনা বা প্লাগ ইন করেছেন?
গিলস

হ্যাঁ, নিয়মগুলি চেষ্টা করে দেখার জন্য আমি এটি সম্পাদন করি। আমি সেই অনুসারে প্রশ্নটি সম্পাদনা করেছি। এখন এইভাবে কিছুক্ষণ উদেব কাজ করে তবে আমি চালাচ্ছি 3.5.0-23-generic
রেডসান্দ্রো

উত্তর:


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আপনি দেখতে পাবেন যে পরিবেশটি ওদেব থেকে কী সেট করা আছে এবং এর সাথে fileআপনি ফাইলের প্রকারটি আবিষ্কার করতে পারবেন।

আপনার ডিভাইসের জন্য কংক্রিট বৈশিষ্ট্যগুলি আবিষ্কার করা যেতে পারে lsusb

lsusb

দেয়

...
বাস 001 ডিভাইস 016: আইডি 152 ডি: 2329 জে ম্যাক্রন প্রযুক্তি কর্পোরেশন / জে ম্যাক্রন ইউএসএ প্রযুক্তি কর্পোরেশন জেএম20329 সাতা সেতু
...


1
এটা মজার! দেখে মনে হচ্ছে এটির / লগ / এ লেখার কোনও অনুমতি নেই। এটা তোলে করেন করার / tmp -র পরিবর্তে / লেখা। আমার ধারণা, এটি আমার পূর্ববর্তী পরীক্ষাগুলি পড়ার কোনও অনুমতি ছিল না।
রেডসান্দ্রো

@ রেডসান্দ্রো এটি পরীক্ষামূলক উদ্দেশ্যে, উদ্দেশ্যমূলক ছিল না, যাইহোক, আমি আনন্দিত এটি সাহায্য করেছে। ;-)
ওলাফ ডিয়েটশে

আমি আপনাকে এই প্রশ্নটি পরীক্ষা করে দেখতে এবং আপনার জ্ঞানটি সেখানে মূল্যবান হতে পারে কিনা তা দেখতে উত্সাহিত করতে চাই । :)
রেডসান্দ্রো

3
আপনি ACTION=="add",নিয়মের সংজ্ঞাটিতে সরাসরি যুক্ত করতে পারেন ।
অবিন্দ্র গলচরণ

4

এটি সরাসরি আপনার প্রশ্ন সম্পর্কে নয় তবে আপনি কী করছেন সে সম্পর্কে। যদি আপনি উদেব থেকে একটি ব্যাকআপ স্ক্রিপ্ট শুরু করেন তবে আপনি দুটি প্রধান সমস্যার মুখোমুখি হবেন:

  1. ডিভাইসটি প্রস্তুত হওয়ার আগে এবং মাউন্ট করার আগে আপনার স্ক্র্যাপিটটি শুরু হতে পারে, আপনি যদি মাউন্ট করার জন্য / ডিভ নোড ব্যবহার করতে চান তবে আপনাকে KERNEL == "sd *" শর্ত রাখতে হবে
  2. আরও গুরুত্বপূর্ণ, যদি আপনার স্কিরিপটি কার্যকর করতে কিছুটা সময় নেয় (যা সহজেই ব্যাকআপ স্ক্রিপ্টের ক্ষেত্রে হতে পারে) এটি শুরু হওয়ার সাথে সাথেই এটি হত্যা করা হবে (প্রায় 5s)
  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"

দ্রষ্টব্য: আমি কেডিই সহ অটো-মাউন্ট ব্যবহার করি তাই আমি ফোল্ডারটি উপস্থিত হওয়ার জন্য পরীক্ষা করি। আপনি উদেব নিয়ম থেকে ফিফোতে / dev / sd * প্যারামিটারটি পাস করতে পারেন এবং স্ক্রিপ্টে নিজে এটি মাউন্ট করতে পারেন। ফিফোতে লিখতে ভুলবেন না যে উদেব কোনও শেল নয় এবং সেই পুনঃনির্দেশটি কাজ করে না। আপনার আরএনআন এর মতো হওয়া উচিত:

RUN + = "/ বিন / শ-সি '/ বিন / প্রতিধ্বনি সংযুক্ত >> / tmp / IomegaUsbPype'"


নামকরণ পাইপ এখানে দুর্দান্ত ব্যবহার। আমি ভাবছিলাম আপনি কেবলমাত্র tmp এ একটি স্বেচ্ছাসেবী ফাইল তৈরি করতে পারেন এবং এটির জন্য নামী পাইপের পরিবর্তে সন্ধান করতে পারেন, সঠিক?
jamescampbell

1

আমি /ubuntu//a/516336 এ একটি সমাধান পোস্ট করেছি এবং আমি সমাধানটি এখানে অনুলিপি-আটকানোও করেছি।

আমি পাইউদেব ব্যবহার করে একটি পাইথন স্ক্রিপ্ট লিখেছিলাম যা আমি পটভূমিতে চালানো ছেড়ে চলেছি । এই স্ক্রিপ্টটি ইউদেব ইভেন্টগুলি শোনায় (এইভাবে এটি খুব দক্ষ) এবং আমি যা কোড চাই তা চালায়। আমার ক্ষেত্রে এটি 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

বুথের স্ক্রিপ্টটি চালানোর জন্য যখন ইউএসবি ডিভাইস isোকানো হয় আমি নীচের সমাধানটি ব্যবহার করি:

পেনড্রাইভ বা অন্য কোনও ইউএসবি স্টোরেজ ফর্ম্যাট করুন এবং এটি করার সময় একটি নাম দিন। তারপরে /etc/rc.local অ্যাড লাইনেls -q /dev/disk/by-label > /home/pi/label.txt

এটি লেবেল.টিএসটিএসএস নামে একটি টেক্সট ফাইল তৈরি করবে (অন্য কোনও নাম হতে পারে)

তারপরে আবার /etc/rc.local এ আরও 2 টি লাইন যুক্ত করুন:

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

এখন ইউএসবি_ড্রাইভ_নামের সাথে প্রতিটা পেনড্রাইভ isোকানো হয় এটি স্ক্রিপ্টটি চালাবে।

সিস্টেম আপ এবং চলমান থাকা অবস্থায় উপরের কয়েকটি সমাধানের সাথে উপরের সমাধানটি ব্যবহার করা যেতে পারে।


প্রশ্নের উত্তর দেয় না: এটি কেবল বুট-টাইমকে কভার করে (এবং udevঅন্যান্য সময়ের জন্য ব্যবহার করা "কয়েকটি সামান্য পরিবর্তন" নয়) এবং রাস্পবেরি পাই। একটি অপ্রয়োজনীয় আছে sudo- rc.localরুট হিসাবে চালায়, এটি একটি প্রিভিজিয়াল এসকেলেশন ইস্যু - একটি সাধারণ ব্যবহারকারী দ্বারা সম্পাদনাযোগ্য একটি ফাইল রুট হিসাবে চালানো হয়।
গার্ট ভ্যান ডেন বার্গ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.