কীভাবে চিরকাল কিছুই করবেন না মার্জিত উপায়ে?


82

আমার একটি প্রোগ্রাম রয়েছে যা দরকারী তথ্য তৈরি করে stdoutতবে তা থেকেও পড়ে stdin। আমি স্ট্যান্ডার্ড ইনপুটটিতে কোনও সরবরাহ না করেই এর স্ট্যান্ডার্ড আউটপুটটিকে কোনও ফাইলে পুনর্নির্দেশ করতে চাই। এখন পর্যন্ত, এত ভাল: আমি এটি করতে পারি:

program > output

আর tty তে কিছু করবেন না।

তবে সমস্যাটি হ'ল আমি এটি ব্যাকগ্রাউন্ডে করতে চাই। যদি আমি করি:

program > output &

প্রোগ্রামটি স্থগিত হয়ে যাবে ("স্থগিত (টিটি ইনপুট)")।

যদি আমি করি:

program < /dev/null > output &

প্রোগ্রামটি তত্ক্ষণাত বন্ধ হয়ে যায় কারণ এটি ইওএফ পৌঁছায়।

দেখে মনে হচ্ছে যে আমার যা দরকার তা হ'ল এমন programকিছুতে পাইপ করা যা অনির্দিষ্ট সময়ের জন্য কিছু করে না এবং পড়ে না stdin। নিম্নলিখিত পদ্ধতির কাজ:

while true; do sleep 100; done | program > output &
mkfifo fifo && cat fifo | program > output &
tail -f /dev/null | program > output &

যাইহোক, এটি সব খুব কুরুচিপূর্ণ। সেখানে রয়েছে একটি মার্জিত উপায় হতে, মানক ইউনিক্স ইউটিলিটি ব্যবহার করে, "কিছুই করতে, অনির্দিষ্টকালের জন্য" থেকে (ভাষান্তর করার man true)। আমি কীভাবে এটি অর্জন করতে পারি? (এখানে কমনীয়তার জন্য আমার প্রধান মাপদণ্ড: কোনও অস্থায়ী ফাইল নেই; ব্যস্ত-অপেক্ষার বা পর্যায়ক্রমিক জাগরণের ব্যবস্থা নেই; কোনও বহিরাগত ইউটিলিটি নেই যতটা সম্ভব সংক্ষিপ্ত))


ব্যবহার করে দেখুন su -c 'program | output &' user। আমি "পরিষেবা / ডেমন" পরিচালনা করার জন্য গ্রহণযোগ্য পদ্ধতি হিসাবে পটভূমি কাজ তৈরির সাথে একই ধরণের প্রশ্ন করতে চলেছি। আমি আরও লক্ষ্য করেছি যে আমি পুনর্নির্দেশ STDERRছাড়াও পুনর্নির্দেশ করতে পারি না STDOUT। সমাধান যেখানে प्रोग्रामএ প্রোগ্রাম বিতে প্রেরণ STDOUTকরে STDIN, তারপরে STDERRএকটি লগ ফাইলে পুনঃনির্দেশ করে:programA 2> /var/log/programA.log | programB 2> /var/log/programB.log 1> /dev/null
এমব্রাউননিc

হতে পারে ... su -c 'while true; do true; done | cat > ~/output &' user?
mbrownnyc

এটা কি ধরনের প্রোগ্রাম?
জোও পোর্তেলা


আপনি যে প্রোগ্রামটি লিখেছেন সেটিতে কেবল একটি স্যুইচ যোগ করবেন না কেন? এছাড়াও, আমি ধরে নিই যে আপনি যদি স্টিডিনটি বন্ধ করে দেন তবে 1<&-এটি আপনার প্রোগ্রাম থেকে প্রস্থান করবে?
w00t

উত্তর:


16

তাদের সমর্থনকারী শেলগুলিতে (ksh, zsh, bash4), আপনি programএকটি সহ-প্রক্রিয়া হিসাবে শুরু করতে পারেন ।

  • ksh: program > output |&
  • zsh, bash:coproc program > output

এটি programএর ইনপুটটি এ থেকে পুনর্নির্দেশের সাথে পটভূমিতে শুরু হয় pipe। পাইপের অপর প্রান্তটি খোলা রয়েছে।

এই পদ্ধতির তিনটি সুবিধা

  • কোন অতিরিক্ত প্রক্রিয়া
  • programমারা যাওয়ার সময় আপনি স্ক্রিপ্ট থেকে প্রস্থান করতে পারেন ( waitএটির জন্য অপেক্ষা করুন)
  • programবন্ধ হয়ে যাবে ( eofশেলটি প্রস্থানিত হলে তার স্টিনে উঠুন)।

এটি কাজ করে বলে মনে হচ্ছে এবং দুর্দান্ত ধারণা বলে মনে হচ্ছে! (সত্যি বলতে কী, আমি শেল বৈশিষ্ট্যের জন্য নয়, আমার কমান্ডের কাছে পাইপ দেওয়ার জন্য কিছু চেয়েছিলাম, তবে এটি খেলতে গিয়ে XY সমস্যা ছিল)) আমি @ পিটি-র পরিবর্তে এই উত্তরটি গ্রহণ করার বিষয়টি বিবেচনা করছি।
a3nm

1
@ এ 3 এনএম, tail -f /dev/nullআদর্শ নয় কারণ এটি প্রতি সেকেন্ডে একটি পঠন করে /dev/null(লিনাক্সে জিএনইউ লেজের বর্তমান সংস্করণগুলি ইনোটাইফাই ব্যবহার করে সেখানে আসলে একটি বাগ রয়েছে )। sleep infবা এর আরও বহনযোগ্য সমতুল্য sleep 2147483647কোনও কমান্ডের জন্য আরও ভাল পন্থা যা সেখানে বসে কোনও আইএমও করে না (লক্ষ্য করুন যে sleepএটি কয়েকটি শেলের মতো তৈরি হয়েছে ksh93বা mksh)।
স্টাফেন চেজেলাস

78

আমি মনে করি না যে আপনি এর চেয়ে আরও মার্জিত পাবেন

tail -f /dev/null

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

আপনার এমন একটি ইউটিলিটি দরকার যা অনির্দিষ্টকালের জন্য চলবে, তার স্টাডআউটটি উন্মুক্ত রাখবে, কিন্তু আসলে স্টাডআউটকে কিছুই লিখবে না এবং স্টিডিনটি বন্ধ হয়ে গেলে প্রস্থান করবে না। yesআসলে কিছু stdout লেখেন। catএর স্টিডিনটি বন্ধ হয়ে গেলে প্রস্থান করবে (বা আপনি যা যা পুনরায় ডাইরেক্ট করেন তা হয়ে গেছে)। আমি মনে করি sleep 1000000000dকাজ করতে পারে, তবে এটি tailপরিষ্কারভাবে আরও ভাল। আমার ডেবিয়ান বাক্সে একটি tailfকমান্ডটি সামান্য ছোট করা আছে।

একটি ভিন্ন জিনিস গ্রহণ করা, কিভাবে অধীনে প্রোগ্রাম চলমান screen?


আমি tail -f /dev/nullপদ্ধতির সেরাটি পছন্দ করি এবং এটি যথেষ্ট মার্জিতও দেখতে পাই , যেহেতু কমান্ডের ব্যবহার উদ্দেশ্যটির সাথে খুব ঘনিষ্ঠভাবে মেলে।
jw013

2
strace tail -f /dev/nullএটি থেকে মনে হয় যে tailব্যবহারগুলি inotifyএবং যে জাগ্রতগুলি মূর্খ ক্ষেত্রে এর মতো ঘটে sudo touch /dev/null। এটি দুঃখজনক যে এর চেয়ে ভাল সমাধান আর নেই বলে মনে হচ্ছে ... আমি আরও অবাক হলাম যে আরও ভাল সমাধান বাস্তবায়নের জন্য কোনটি সঠিক সিস্কেল ব্যবহার করা উচিত।
a3nm

5
@ a3nm সিস্কেলটি হবে pauseতবে এটি শেল ইন্টারফেসের সাথে সরাসরি উন্মুক্ত নয়।
গিলস

পিটি: আমি জানি screen, তবে এটি পরীক্ষার উদ্দেশ্যে শেল স্ক্রিপ্ট থেকে প্রোগ্রামের একাধিক উপস্থিতি চালানো হয়, সুতরাং এটি ব্যবহার screenকরা কিছুটা ওভারকিল।
a3nm

3
@ সিলিমুনকি সিলি বানর, ওয়েলজে-র উত্তরটি ভুল (স্টিডিনে অসীম শূন্য প্রেরণ করে)।
পিটি

48

sleep infinity আমি জানি এর সবচেয়ে পরিষ্কার সমাধান।

আপনি ব্যবহার করতে পারেন infinityকারণ sleepএকটি ফ্লোটিং পয়েন্ট সংখ্যা গ্রহণ করে * , যা হতে পারে দশমিক , হেক্সাডেসিমেল , অনন্ত , অথবা NaN অনুযায়ী man strtod

* এটি পসিক্স স্ট্যান্ডার্ডের অংশ নয়, তাই পোর্টেবল হিসাবে নয় tail -f /dev/null। তবে এটি জিএনইউ কোর্টিলস (লিনাক্স) এবং বিএসডি (ম্যাকের জন্য ব্যবহৃত) (ম্যাকের নতুন সংস্করণগুলিতে দৃশ্যত সমর্থিত নয় - মন্তব্য দেখুন) এ সমর্থিত।


হাহাহা, সত্যিই এটি একটি দুর্দান্ত পদ্ধতির। :)
a3nm

@ a3nm: ধন্যবাদ:) BSD এবং Macsleep infinity এও কাজ করে বলে মনে হচ্ছে ।
জাজ

অসীম ঘুমন্ত প্রক্রিয়া কোন ধরণের সংস্থান গ্রহণ করে? শুধু র‌্যাম?
সিএমসিডিগ্রাগনকাই

1
এই উত্তরটি দাবি করেছে যে sleep infinityসর্বোচ্চ 24 দিনের জন্য অপেক্ষা করে; কে ঠিক আছে?
এনএইচ 2

1
@ জাজ আমি এখন বিষয়টি বিস্তারিতভাবে তদন্ত করেছি। দেখা যাচ্ছে যে আপনি প্রাথমিকভাবে সঠিক ছিলেন! sleepইউটিলিটি 24 দিন সীমাবদ্ধ নয় ; এটি কেবলমাত্র প্রথম সিস্কেল যা 24 দিনের জন্য ঘুমায় এবং এরপরে এটি আরও বেশি সিস্কেলগুলি করবে। : এখানে আমার মন্তব্য দেখুন stackoverflow.com/questions/2935183/...
nh2

19
sleep 2147483647 | program > output &

হ্যাঁ, 2^31-1একটি সীমাবদ্ধ সংখ্যা, এবং এটি চিরকালের জন্য চলবে না , তবে অবশেষে যখন ঘুম শেষ হবে তখন আমি আপনাকে 1000 ডলার দেব। (ইঙ্গিত: ততক্ষণে আমাদের মধ্যে একজন মারা যাবে।)

  • অস্থায়ী ফাইল নেই; চেক করুন।
  • কোন ব্যস্ত-অপেক্ষার বা পর্যায়ক্রমিক জাগরণ নেই; চেক
  • বিদেশী কোন উপযোগিতা নেই; চেক করুন।
  • যতটা সম্ভব সংক্ষিপ্ত ঠিক আছে, এটি আরও কম হতে পারে।

5
bash: ঘুম $ ((64 # 1 _____)) | প্রোগ্রাম> আউটপুট এবং
দিয়েগো টরেস মিলানো

যে 68 বছর ধরে ঘুমায়, এই 98 টি শতাব্দীর জন্য ঘুমায় : sleep 2147483647d...
agc

9

আপনি একটি বাইনারি তৈরি করতে পারেন যা এর সাথে এটি করে:

$ echo 'int main(){ pause(); }' > pause.c; make pause

5

"অনির্দিষ্টকালের জন্য কিছু না করার জন্য" স্ট্যান্ডার্ড ইউনিক্স ইউটিলিটিগুলি ব্যবহার করে এখানে আরও একটি পরামর্শ দেওয়া হয়েছে ।

sh -c 'kill -STOP $$' | program > output

এটি তাত্ক্ষণিকভাবে প্রেরিত SIGSTOPশেলটিকে জ্বালিয়ে দেয় যা প্রক্রিয়াটি স্থগিত করে। এটি আপনার প্রোগ্রামে "ইনপুট" হিসাবে ব্যবহৃত হয়। এর পরিপূরকটি SIGSTOPহ'ল SIGCONT, যদি আপনি জানেন শেলটির পিআইডি 12345 রয়েছে তবে আপনি kill -CONT 12345এটি চালিয়ে যেতে পারবেন ।


2

লিনাক্সে, আপনি এটি করতে পারেন:

read x < /dev/fd/1 | program > output

লিনাক্সে, খোলার / ডিভ / এফডি / এক্স যেখানে এক্স পাইপের লেখার শেষ প্রান্তের একটি ফাইল বর্ণনাকারী, আপনি পাইপের পড়ার শেষ পাবেন, সুতরাং এখানে প্রোগ্রামের স্টিডিনের মতোই। সুতরাং মূলত, readকখনই ফিরে আসবে না, কারণ সেই পাইপে কেবল লিখতে পারে তা নিজেই, এবং readকোনও কিছুই আউটপুট দেয় না।

এটি ফ্রিবিএসডি বা সোলারিসেও কাজ করবে তবে অন্য কারণে for সেখানে, ডিভ / ডি / এফডি / 1 খোলার ফলে আপনি এফডি 1 তে সমান রিসোর্স পাবেন যা আপনি আশা করেছিলেন এবং লিনাক্স ব্যতীত বেশিরভাগ সিস্টেম যেমন পাইপের লেখার শেষ হয়। তবে, ফ্রিবিএসডি এবং সোলারিসে পাইপগুলি দ্বিপাক্ষিক ction সুতরাং যতক্ষণ programনা তার স্ট্ডিনে লিখিত না হয় (কোনও অ্যাপ্লিকেশন দেয় না), readপাইপের সেই দিক থেকে পড়তে কিছুই পাবে না।

readকেবলমাত্র লেখার জন্য কেবল ফাইল বর্ণনাকারী থেকে পড়ার চেষ্টা করার সময় সিস্টেমে পাইপগুলি দ্বি নির্দেশমূলক নয়, সম্ভবত একটি ত্রুটি সহ ব্যর্থ হবে। এছাড়াও মনে রাখবেন যে সমস্ত সিস্টেমে নেই /dev/fd/x


খুব সুন্দর! আসলে আমার পরীক্ষাগুলি আপনার xবাশ দিয়ে দরকার নেই ; Zsh এর সাথে আপনি আরও করতে পারেন readএবং এটি কাজ করে (যদিও আমি বুঝতে পারি না কেন!)। এই কৌশলটি কি লিনাক্স-নির্দিষ্ট, বা এটি সমস্ত * নিক্স সিস্টেমে কাজ করে?
a3nm

@ a3nm, আপনি যদি readএকা করেন তবে এটি স্ট্ডিনের কাছ থেকে পড়বে। সুতরাং এটি যদি টার্মিনাল হয় তবে এটি লিখতে হবে যতক্ষণ না আপনি এন্টার টিপেন।
স্টাফেন চেজেলাস

অবশ্যই, আমি বুঝতে পারি পড়া কি করে। আমি যা বুঝতে পারি না তা হ'ল পটভূমি প্রক্রিয়ায় পঠন সহ টার্মিনাল থেকে পড়া বাশ দিয়ে বাধা দিচ্ছে তবে zsh দিয়ে নয়।
a3nm

@ এ 3 এনএম, আপনার অর্থ কী তা আমি নিশ্চিত নই। আপনি কেবল কি করতে পারেন তাread বোঝাতে এবং এটি কার্যকর হয় ?
স্টাফেন চেজেলাস

আমি বলছি যে zsh এর সাহায্যে আপনি ঠিক করতে পারেন read | program > outputএবং এটি আপনার পরামর্শ মত একইভাবে কাজ করে। (এবং আমি কেন পাই না))
a3nm

0

স্টাফেন শেজেলাসের read সমাধান ম্যাক ওএস এক্সেও কাজ করে যদি কোনও রিডিং এফডি চালু হয় /dev/fd/1

# using bash on Mac OS X
# -bash: /dev/fd/1: Permission denied
read x </dev/fd/1 | cat >/dev/null
echo ${PIPESTATUS[*]}   #  1 0

exec 3<&- 3</dev/fd/1
read x 0<&3 | cat >/dev/null
echo ${PIPESTATUS[*]}   #  0 0

tail -f /dev/nullকোনও স্ক্রিপ্টে হত্যা করতে সক্ষম হওয়ার জন্য (উদাহরণস্বরূপ সাইন ইন), tailকমান্ডটি ব্যাকগ্রাউন্ড করা এবং wait

#!/bin/bash
# ctrl-c will kill tail and exit script
trap 'trap - INT; kill "$!"; exit' INT
exec tail -f /dev/null & wait $!

-2

/dev/zeroস্ট্যান্ডার্ড ইনপুট হিসাবে পুনর্নির্দেশ !

program < /dev/zero > output &

9
এটি তার প্রোগ্রামকে অসীম সংখ্যক শূন্য-বাইট দেয় ... যা দুঃখের বিষয়, এটিকে ব্যস্ততা তৈরি করবে।
জান্ডার

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

2
দুঃখিত, ওপি স্টিডিন ব্যবহার করে, সুতরাং এটি তার ইনপুটটি মুছে ফেলবে এবং / dev / শূন্য থেকে অঙ্কিত হবে। আমার পরের বার দুবার পড়া উচিত! যদি ওপি স্টিডিন ব্যবহার না করে, তবে এটি আমার দেখা সর্বাধিক মার্জিত সমাধান হবে এবং ব্যস্ততার জন্য অপেক্ষা করা হবে না।
বোকা মুনকি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.