আমি কী-স্ট্রোক দিয়ে বাশ স্ক্রিপ্ট থেকে ডেকে আউট টাইমআউটকে হত্যা করতে পারি না?


11

[সম্পাদনা করুন: সমস্ত প্রসেস প্রক্রিয়াগুলিকে কীভাবে হত্যা করতে হবে এমন প্রশ্ন জিজ্ঞাসা করা অন্য কিছু প্রশ্নের সাথে একই রকম দেখাচ্ছে - উত্তরগুলি সমস্তই প্যাকিল ব্যবহার করে বলে মনে হচ্ছে। সুতরাং আমার প্রশ্নের মূলটি হতে পারে: কোনও স্ক্রিপ্ট দ্বারা উদ্ভূত সমস্ত প্রক্রিয়াতে Ctrl-C / Z প্রচার করার কোনও উপায় আছে কি?]

কোরটিলস ( এখানে আলোচনা করা হয়েছে ) থেকে কমান্ড recদিয়ে কোনও সাক্স কল করার সময়, কোনও বাশ স্ক্রিপ্টের মধ্যে থেকে এটি চাওয়ার পরে কী-স্ট্রোক দিয়ে একে হত্যা করার কোনও উপায় বলে মনে হয় না।timeout

উদাহরণ:

timeout 10 rec test.wav

... বাশ থেকে Ctrl+ Cবা Ctrl+ দিয়ে হত্যা করা যেতে পারে Z, তবে যখন কোনও স্ক্রিপ্টের ভেতর থেকে ডাকা হত না।

timeout 10 ping nowhere

... বাশ থেকে Ctrl+ Cবা Ctrl+ Zদিয়ে Ctrlএবং Zযখন এটি কোনও স্ক্রিপ্টের ভিতরে থেকে চালানো হয় তখন + দিয়ে হত্যা করা যেতে পারে ।

আমি প্রক্রিয়া আইডিটি খুঁজে পেতে পারি এবং সেভাবে এটি হত্যা করতে পারি তবে কেন আমি একটি স্ট্যান্ডার্ড ব্রেক ব্রেক কীস্ট্রোকটি ব্যবহার করতে পারি না? এবং আমার স্ক্রিপ্টটি গঠন করার কোনও উপায় আছে যাতে আমি পারি?


2
Ctrl + Z প্রক্রিয়াগুলিকে হত্যা করে না, কেবল তাদের বিরতি দেয়। তারা চলমান রাখা যদি আপনি দিতে হবে bgএর fgকমান্ড। যাইহোক, আপনার 1 ম এবং 3 ডি উদাহরণের মধ্যে কোনও পার্থক্য রয়েছে?
টেরডন

আমি না timeoutআমার সিস্টেম কিন্তু মেরে ফেলতে চায় sleepকাজ তা সরাসরি কমান্ড-লাইন স্পষ্টভাবে টাইপ করা হচ্ছে sourced মৃত্যুদন্ড কার্যকর, বা গৃহীত দোভাষীর মাধ্যমে
কেভিন

@ এটারডন ধন্যবাদ, আমি উদাহরণগুলি পরিষ্কার করে দিয়েছি।
17-18 এ মিলিত হয়েছে

উত্তর:


18

সিগন্যাল কীগুলি যেমন Ctrl+ Cঅগ্রভাগ প্রক্রিয়া গোষ্ঠীর সমস্ত প্রক্রিয়াতে একটি সংকেত প্রেরণ করে ।

সাধারণ ক্ষেত্রে, একটি প্রক্রিয়া গ্রুপ হ'ল পাইপলাইন। উদাহরণস্বরূপ, মধ্যে head <somefile | sort, প্রক্রিয়াটি চলমান headএবং প্রক্রিয়াটি চালানো sortএকই শৃঙ্খলা গ্রুপে রয়েছে যেমন শেল, সুতরাং তারা সকলেই সংকেতটি গ্রহণ করে। আপনি যখন ব্যাকগ্রাউন্ডে ( somecommand &) কাজ পরিচালনা করেন তখন সেই কাজটি তার নিজস্ব প্রক্রিয়া গোষ্ঠীতে থাকে, সুতরাং Ctrl+ টিপে Cএটি প্রভাবিত করে না।

timeoutপ্রোগ্রাম নিজস্ব প্রক্রিয়া গ্রুপ নিজেই স্থাপন করা হয়। উত্স কোড থেকে:

/* Ensure we're in our own group so all subprocesses can be killed.
   Note we don't just put the child in a separate group as
   then we would need to worry about foreground and background groups
   and propagating signals between them.  */
setpgid (0, 0);

যখন একটি সময়সীমা ঘটে তখন timeoutপ্রক্রিয়া গ্রুপটি হ'ল যার সদস্য এটি হ'ল সরল অভিযাত্রীর মধ্য দিয়ে যায়। যেহেতু এটি নিজেকে আলাদা প্রক্রিয়া গোষ্ঠীতে ফেলেছে, তাই এর প্যারেন্ট প্রসেসটি গ্রুপে থাকবে না। এখানে একটি প্রক্রিয়া গোষ্ঠী ব্যবহার করে নিশ্চিত করা হয় যে যদি শিশু অ্যাপ্লিকেশনটি বেশ কয়েকটি প্রক্রিয়াতে জালিয়াতি করে, তার সমস্ত প্রক্রিয়াগুলি সংকেতটি গ্রহণ করবে।

আপনি যখন timeoutকমান্ড লাইনে সরাসরি চালান এবং Ctrl+ টিপুন C, ফলস্বরূপ স্বাক্ষরটি timeoutশিশু প্রক্রিয়া দ্বারা এবং উভয়ই গৃহীত হয় , তবে ইন্টারেক্টিভ শেল দ্বারা নয় যা timeoutঅভিভাবক প্রক্রিয়া। যখন timeoutকোনও স্ক্রিপ্ট থেকে ডাকা হয়, কেবল স্ক্রিপ্টটি চালিত শেলটি সিগন্যালটি গ্রহণ করে: timeoutএটি ভিন্ন প্রক্রিয়া গোষ্ঠীর মধ্যে থেকে এটি পায় না।

আপনি trapবিল্টিন দিয়ে শেল স্ক্রিপ্টে একটি সিগন্যাল হ্যান্ডলার সেট করতে পারেন । দুর্ভাগ্যক্রমে, এটি এত সহজ নয়। এই বিবেচনা:

#!/bin/sh
trap 'echo Interrupted at $(date)' INT
date
timeout 5 sleep 10
date

আপনি যদি 2 সেকেন্ড পরে Ctrl+ Cটিপেন, এটি এখনও পুরো 5 সেকেন্ডের জন্য অপেক্ষা করে, তবে "বাধা" বার্তাটি মুদ্রণ করুন। এর কারণ শেলটি অগ্রভাগের কাজ সক্রিয় থাকাকালীন ট্র্যাপ কোড চালানো থেকে বিরত থাকে।

এর প্রতিকারের জন্য, পটভূমিতে কাজটি চালান। সিগন্যাল হ্যান্ডলারে, প্রক্রিয়া গোষ্ঠীতে killসিগন্যালটি রিলে কল করুন timeout

#!/bin/sh
trap 'kill -INT -$pid' INT
timeout 5 sleep 10 &
pid=$!
wait $pid

ভীষণ স্নিগ্ধ - সুন্দরভাবে কাজ করেছেন! আমি এখন অনেক বেশি স্মার্ট, মেরি!
মিলিত হয়েছে

13

গিলস কর্তৃক প্রদত্ত দুর্দান্ত উত্তরের ভিত্তিতে বিল্ডিং। টাইমআউট কমান্ডটির একটি অগ্রভাগ বিকল্প রয়েছে, যদি এটি ব্যবহার করা হয় তবে একটি সিটিআরএল + সি টাইমআউট কমান্ডটি প্রস্থান করবে।

#!/bin/sh
trap 'echo caught interrupt and exiting;exit' INT
date
timeout --foreground 5 sleep 10
date

এটি দুর্দান্ত উত্তর - গ্রহণযোগ্য উত্তরের চেয়ে সহজ এবং timeoutজিএনইউ কোর্টিলগুলি ব্যবহার করে আমার পক্ষে ভাল কাজ করেছে ।
রিচভেল

1

মূলত Ctrl+ সিগন্যাল Cপ্রেরণ করে SIGINT, যখন Ctrl+ Z SIGTSTPসংকেত প্রেরণ করে ।

SIGTSTPকেবল প্রক্রিয়াটি থামায়, একটি SIGCONTএটি চালিয়ে যাবে।

এটি অগ্রভাগ-প্রক্রিয়াতে কাজ করে যা কমান্ড-লাইনে তৈরি হয়েছিল।

যদি আপনার প্রক্রিয়াটি একটি ব্যাকগ্রাউন্ড-প্রক্রিয়া হয় তবে আপনাকে সেই সংকেত প্রক্রিয়াগুলিতে অন্যভাবে প্রেরণ করতে হবে। killএটা করবে। তাত্ত্বিকভাবে একটি "-" - সেই হত্যার অপারেটর দ্বারা শিশু প্রক্রিয়াগুলিও সিগন্যাল করা উচিত তবে এই কদাচিৎ প্রত্যাশা অনুযায়ী কাজ করে।

আরও পড়ার জন্য: ইউনিক্স-সিগন্যাল


এটি সত্য, কমপক্ষে "কদাচিৎ প্রত্যাশা অনুযায়ী কাজ করে" (যা আপনার প্রত্যাশার উপর নির্ভর করে - আপনার প্রক্রিয়া দলগুলি সম্পর্কে পড়া উচিত) তবে সম্পূর্ণ অপ্রাসঙ্গিক। প্রশ্নটি SIGINT এবং SIGTSTP সম্পর্কে কোনও বিভ্রান্তির বিশ্বাসঘাতকতা করে না।
গিলস 'অসন্তুষ্ট হওয়া বন্ধ করুন'

0

বিদ্যমান স্ক্রিপ্টগুলির জন্য "সন্ধান করুন এবং প্রতিস্থাপন করুন" পদ্ধতির মাধ্যমে @ গিলিজের উত্তরকে উন্নত করা :

  1. আপনার কোডের শুরুতে এই স্নিপেটটি যুক্ত করুন:
declare -a timeout_pids
exec 21>&1; exec 22>&2 # backup file descriptors, see /superuser//a/1446738/187576
my_timeout(){
    local args tp ret
    args="$@"
    timeout $args &
    tp=$!
    echo "pid of timeout: $tp"
    timeout_pids+=($tp)
    wait $tp
    ret=$?
    count=${#timeout_pids[@]}
    for ((i = 0; i < count; i++)); do
        if [ "${timeout_pids[i]}" = "$tp" ] ; then
            unset 'timeout_pids[i]'
        fi
    done
    return $ret
}
  1. আপনার INTহ্যান্ডলারের মধ্যে নিম্নলিখিত কোডটি যুক্ত করুন (বা মার্জ করুন) :
pre_cleanup(){
    exec 1>&21; exec 2>&22 # restore file descriptors, see /superuser//a/1446738/187576
    echo "Executing pre-cleanup..."
    for i in "${timeout_pids[*]}"; do
        if [[ ! -z $i ]]; then
            #echo "Killing PID: $i"
            kill -INT -$i 2> /dev/null
        fi
    done
    exit
}

trap pre_cleanup INT
  1. আপনার স্ক্রিপ্টে ফাংশন timeoutসহ কমান্ডগুলি প্রতিস্থাপন করুন my_timeout

উদাহরণ

এখানে একটি উদাহরণ স্ক্রিপ্ট:

#!/bin/bash

# see "killing timeout": /unix//a/57692/65781
declare -a timeout_pids
exec 21>&1; exec 22>&2 # backup file descriptors, see /superuser//a/1446738/187576
my_timeout(){
    local args tp ret
    args="$@"
    timeout $args &
    tp=$!
    echo "pid of timeout: $tp"
    timeout_pids+=($tp)
    wait $tp
    ret=$?
    count=${#timeout_pids[@]}
    for ((i = 0; i < count; i++)); do
        if [ "${timeout_pids[i]}" = "$tp" ] ; then
            unset 'timeout_pids[i]'
        fi
    done
    return $ret
}

cleanup(){
    echo "-----------------------------------------"
    echo "Restoring previous routing table settings"
}

pre_cleanup(){
    exec 1>&21; exec 2>&22 # restore file descriptors, see /superuser//a/1446738/187576
    echo "Executing pre-cleanup..."
    for i in "${timeout_pids[*]}"; do
        if [[ ! -z $i ]]; then
            echo "Killing PID: $i"
            kill -INT -$i 2> /dev/null
        fi
    done
    exit
}

trap pre_cleanup INT
trap cleanup EXIT

echo "Executing 5 temporary timeouts..."
unreachable_ip="192.168.44.5"
my_timeout 1s ping -c 1 "$unreachable_ip" &> /dev/null 
my_timeout 1s ping -c 1 "$unreachable_ip" &> /dev/null 
my_timeout 1s ping -c 1 "$unreachable_ip" &> /dev/null 
my_timeout 1s ping -c 1 "$unreachable_ip" &> /dev/null 
my_timeout 1s ping -c 1 "$unreachable_ip" &> /dev/null 
echo "ctrl+c now to execute cleanup"
my_timeout 9s ping -c 1 "$unreachable_ip" &> /dev/null 
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.