কীভাবে পাইপলাইনটি ফাইলের শেষের অপেক্ষা বা ত্রুটির পরে থামবে?


12

পাইপ শেননিগানগুলিতে এই ভিডিওটি দেখার পরে আমি নিম্নলিখিত আদেশটি চেষ্টা করেছি ।

man -k . | dmenu -l 20 | awk '{print $1}' | xargs -r man -Tpdf | zathura -

এটি মূলত ব্যবহারকারীর মধ্যে একটি নির্বাচন করার জন্য ম্যানপেইজের তালিকা মুদ্রণ করে, তারপরে এটি চালনার জন্য xargs ব্যবহার করে man -Tpdf %(xargs ইনপুট থেকে ম্যানপেজ গিটের পিডিএফ স্টাডাউট করতে প্রিন্ট করে) এবং পিডিএফ পিডিএফ পাঠকের কাছে প্রেরণ করে (জাথুরা )।

সমস্যাটি হ'ল (আপনি ভিডিওতে দেখতে পাচ্ছেন) পিএমএফ পাঠক আমি ডেমেনুতে একটি ম্যানপেজ নির্বাচন করার আগেই শুরু হয়। এবং যদি আমি Esc এ ক্লিক করি এবং কোনওটি না নির্বাচন করি, পিডিএফ পাঠক এখনও কোনও নথি না দেখিয়ে খোলা আছে।

আমি যখন পিডিএফ পাঠককে (এবং কোনও পাইপ চেইনের অন্য কোনও কমান্ড) কেবল তখনই চালাতে পারি যখন এর ইনপুটটি ফাইলের শেষের দিকে পৌঁছে যায় বা যখন এটি কোনও ইনপুট পায়? অথবা, বিকল্পভাবে, শৃঙ্খলিত কমান্ডগুলির মধ্যে একটি শূন্য-বহির্গমন স্থিতি ফিরে পাওয়ার পরে আমি কীভাবে থামার জন্য পাইপ চেইন তৈরি করতে পারি (যাতে ডেমেনু যদি কোনও বিকল্প নির্বাচন না করার জন্য ত্রুটি দেয় তবে নিম্নলিখিত কমান্ডগুলি চালিত হয় না)?


1
আপনি কোন শেল ব্যবহার করছেন? এই বাশ কি?
terdon

আমি এটি ব্যাশ, zsh এবং sh এ চেষ্টা করেছি। তাদের সবার আচরণ একই রকম ছিল।
সেনিনাহা

2
হ্যাঁ, আচরণটি আদর্শ, আমি pipefailকুশলান্দার উত্তরে উল্লিখিত বাশের বিকল্পের কারণে কোন শেল জিজ্ঞাসা করেছি asked
terdon

উত্তর:


12

আমি যখন পিডিএফ পাঠককে (এবং কোনও পাইপ চেইনের অন্য কোনও কমান্ড) কেবল তখনই চালাতে পারি যখন এর ইনপুটটি ফাইলের শেষের দিকে পৌঁছে যায় বা যখন এটি কোনও ইনপুট পায়?

এখানে রয়েছে ifne(ডেবিয়ান এটি moreutilsপ্যাকেজে রয়েছে):

ifne কেবলমাত্র যদি স্ট্যান্ডার্ড ইনপুট খালি না থাকে তবে নিম্নলিখিত কমান্ডটি চালায়।

আপনার ক্ষেত্রে:

 | ifne zathura -

উত্তরের জন্য ধন্যবাদ, আমি এই আদেশ জানি না! এই কমান্ডের (এবং অন্যদের moreutils) মূল ইউনিক্স হয়েছে এবং posix দ্বারা নির্দিষ্ট করা উচিত ছিল ... এটা যেমন একটি মৌলিক এবং ইউনিক্স পর টুল ...
Seninha

@ সিনিনাহা এর সরলতা ifneকিছুটা ধোঁকাবাজি । ইউনিক্সের কোনও "পাইপ পিক" অপারেশন নেই, তাই ifneনির্ভরশীল কমান্ড চালানোর সিদ্ধান্ত নেওয়ার আগে অবশ্যই কমপক্ষে একটি বাইট পড়তে হবে। এর অর্থ এটি কেবল পরীক্ষা করতে পারে না এবং কমান্ডটি কার্যকর করতে পারে না, তবে অবশ্যই অন্য একটি পাইপ তৈরি করতে হবে, নির্ভরশীল কমান্ডটি চালানোর জন্য অন্য প্রক্রিয়াটি কাঁটাচামচ করতে হবে এবং স্টিডিন পাইপ থেকে ডাউন স্ট্রিম পাইপে পুরো প্রবাহটি অনুলিপি করতে হবে। যদি "ইনপুট খালি" কেসটি সাধারণ না হয় ifne, তবে এটি গড়ে সংরক্ষণের চেয়ে সহজেই আরও বেশি সংস্থান খরচ করতে পারে।

@ Wumpus.Q.Wumbley এটি একটি পৌরাণিক কাহিনী - পাইপে ডেটা আছে কিনা তা নির্ধারণ করতে আপনাকে কোনও বাইট পড়তে হবে নাএখানে দেখুন । এবং লিনাক্সে আপনি আসলে কোনও পাইপ থেকে ডেটা উঁকি দিতে পারেন (যেমন এটি অপসারণ না করে ডেটাটি পড়ুন)। আমি এখানে এবং "ক্যানোনিকাল" উত্তরের মন্তব্যগুলিতে আরও উল্লেখ করেছি তবে এগুলি মোডগুলি দ্বারা সরানো হয়েছিল কারণ তারা সম্ভবত অনুভব করেছিলেন যে এই তথ্যগুলি উত্তরের অদ্ভুততা থেকে বিরত থাকার মতো।
মস্কি

6

পিডিএফ ফাইলগুলি সন্ধানযোগ্য বলে মনে করা হচ্ছে; যে কোনও পিডিএফ ভিউয়ারকে প্রথমে ট্রেলারটি দেখতে হবে এবং সেখান থেকে এক্সরেফ টেবিল থেকে অফসেটগুলিতে ঝাঁপিয়ে পড়তে হবে।

যেহেতু পাইপগুলি সন্ধানযোগ্য নয়, zathuraএকটি অবলম্বন কৌশল ব্যবহার করছে, যেখানে এটি সমস্ত ইনপুট কোনও অস্থায়ী ফাইলটিতে অনুলিপি করছে এবং তারপরে সেই অস্থায়ী ফাইলটি সাধারণভাবে ব্যবহার করুন। এই ধরণের "চালাক" কৌশলটি মিথ্যা আশা তৈরি করছে এবং পিডিএফ ফাইলগুলি স্ট্রিমযোগ্য বলে ধরে নিতে লোককে নেতৃত্ব দিচ্ছে।

কিন্তু কোন পথে, zathuraসত্যিই আছে ডকুমেন্ট প্রদর্শন করার আগে ফাইলের শেষে জন্য অপেক্ষা করুন, আপনি যে hapen করার জন্য কিছু করতে হবে না:

(sleep 10; cat file.pdf) | zathura -
# will really show the content of file.pdf after 10 seconds

সমস্যাটি হ'ল zathuraযদি ফাইলটি ঠিক থাকে তবে উইন্ডোটি খোলার কোনও বিকল্প নেই এবং যদি সমস্যা না হয় তবে কোনও ত্রুটি সহ প্রস্থান করুন - এটি কেবল সেখানেই থাকবে যেমন সবকিছু ঠিক আছে:

$ dd if=file.pdf bs=50000 count=1 status=none | zathura -
error: could not open document  # its window still hanging around showing nothing

$ echo $?
0  # really?

এমনকি যদি আপনি নিজেই একটি অস্থায়ী ফাইলে আউটপুটটি পুনঃনির্দেশ করে চলেছেন, এবং কেবল zathuraযদি সবকিছু ঠিকঠাক হয় তবে চলতে থাকে, কোনও zathuraকারণ বা অন্য কোনও কারণে আউটপুট পছন্দ না হলে ব্যবহারকারী একটি কালো উইন্ডো দিয়ে পরিবেশন করবেন না এমন কোনও গ্যারান্টি নেই there's ।


BTW,

man -X man

X11 উইন্ডোতে একটি ম্যানপেজ প্রদর্শন করবে gxditview, এমনকি যদি এটি '70 ;-) এর বাইরে থেকে সরাসরি দেখায়

এবং, অবশ্যই, আপনি সর্বদা ব্যবহার করতে পারেন:

... | xargs xterm -e man

যা অন্যান্য অনেকগুলি বর্ধন ছাড়াও অনুসন্ধান এবং সঠিক পাঠ্য নির্বাচনের ক্ষেত্রে আপনাকে নিয়মিত প্রকাশ করতে দেয়।


6

পাইপলাইনে সমস্ত কমান্ড একই সাথে শুরু হয়। পাইপগুলির মধ্যে এটি কেবলমাত্র I / O যা তাদের সিঙ্ক্রোনাইজ করে। এছাড়াও, পাইপটির বাফার যতটা অনুমতি দেয় তেমন কোনও পাইপ রাখতে পারে।

সুতরাং আপনি পাইপলাইনের এক পর্যায়ে চালানো এড়াতে পারবেন না, কারণ

  1. অন্য যে সমস্ত ধাপ যেভাবেই শুরু করা হবে ততক্ষণে সেই পর্যায়ে কমান্ডটি শুরু হয়ে যায় এবং
  2. যদি কমান্ডটি পাইপের উপর দিয়ে আসা ইনপুটটিকে গ্রাস না করে তবে এটি পাইপলাইনের পূর্ববর্তী পর্যায়ে অবরুদ্ধ হবে।

পরিবর্তে, পাইপলাইন শেষ হতে দেওয়ার সময় কোনও ফাইলে আউটপুট লিখুন। তারপরে সেই ফাইলটি ব্যবহার করুন।

উদাহরণ (একটি তর্ক হিসাবে একটি ফাংশন হিসাবে):

myman () {
    tmpfile=$( mktemp )

    if man -k "$1" | dmenu -l 20 | awk '{print $1}' | xargs -r man -Tpdf >"$tmpfile" && [ -s  "$tmpfile" ]
    then
        zathura "$tmpfile"
    fi

    rm -f "$tmpfile"
}

zathuraপাইপলাইন ব্যর্থ হলে ( xargsঅংশটি শূন্য-শূন্য ফিরে এসেছে) বা উত্পন্ন ফাইলটি খালি থাকলে এটি অতিরিক্তভাবে প্রোগ্রামটি চালায় না ।

ইন bashশেল, এছাড়াও আপনি সেট করতে চান পারে pipefailসঙ্গে শেল বিকল্প set -o pipefailপাইপলাইন পাইপলাইন এটি ব্যর্থ হয় প্রথম কমান্ডের প্রস্থান অবস্থা আসতে আছে। এবং আপনি tmpfileপরিবর্তনশীল করতে চান local:

myman () {
    local tmpfile=$( mktemp )

    if [ -o pipefail ]; then
        set -o pipefail
        trap 'set +o pipefail' RETURN
    fi

    if man -k "$1" | dmenu -l 20 | awk '{print $1}' | xargs -r man -Tpdf >"$tmpfile"
    then
        zathura "$tmpfile"
    fi

    rm -f "$tmpfile"
}

এটি pipefailফাংশনটির সময়কালের জন্য বিকল্পটি সেট করে , যদি এটি ইতিমধ্যে সেট করা না থাকে এবং প্রয়োজনে এটি আনসেট করে। এটি -sআউটপুট ফাইলে পরীক্ষা থেকে মুক্তি পেয়ে যায় ।


1
কেন rm -f? আপনি কি এমন মামলার কথা ভাবছেন যেখানে পাইপটি tmpfile এর অনুমতি পরিবর্তন করে?
terdon

2
@ স্টারডন আমি এমন মামলাগুলির কথা ভাবছি যেখানে অস্থায়ী ফাইলটি অকালপূর্বক সরানো হয়। rm -fফাইলটি ইতিমধ্যে মুছে ফেলা হলে ত্রুটিযুক্ত হবে না (সম্ভবত zathura, আমি জানি না)।
কুসালানন্দ

প্রথম কাজটি প্রত্যাশার মতো কাজ করে না: এটি জাঠুরা একটি কালো উইন্ডো দেখায়, তবে এখন পাইথলাইনটি চালানোর পরিবর্তে পাইথলাইন শেষ হওয়ার পরে জাথুরা চালায়। এটি হ'ল পাইপলাইনটি xargs এর প্রস্থান স্থিতি ফিরে আসে, যা 0 হয় pip পাইপলাইনে যে কমান্ডটি ব্যর্থ হয় তা ডেমেনু হয় (যা আমি যখন কিছু না নির্বাচন করি তখন 1 ফিরে আসে)। বিকল্পযুক্ত বাশ ফাংশন pipefailপ্রত্যাশিত হিসাবে কাজ করে (এবং zsh এও, যার একই বিকল্প রয়েছে)।
সেনিনাহা

1
@ সিনিহা আমি প্রথম ফাংশনটি ঠিক করে দিয়েছি যে উত্পন্ন ফাইলটি খালি নেই কিনা তা পরীক্ষা করে।
কুসালানন্দ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.