কথোপকথনের নিজস্ব সরঞ্জামগুলি ব্যবহার করে: - আউটপুট-এফডি পতাকা
আপনি যদি ডায়লগের জন্য ম্যান পৃষ্ঠাটি পড়েন, তবে বিকল্প রয়েছে --output-fd
, যা আপনাকে স্পষ্টভাবে সেট করতে দেয় যেখানে আউটপুট কোথায় যায় (STDOUT 1, STDERR 2), পরিবর্তে ডিফল্টর পরিবর্তে STDERR এ যায়।
বেলো আপনি আমাকে নমুনা dialog
কমান্ডটি চালিত দেখতে পাচ্ছেন , স্পষ্টভাবে উল্লেখ করে যে আউটপুটটি অবশ্যই ফাইল বর্ণনাকারী 1 এ যেতে হবে, যা আমাকে এটি আমারওয়াইরে সংরক্ষণ করতে দেয়।
MYVAR=$(dialog --inputbox "THIS OUTPUT GOES TO FD 1" 25 25 --output-fd 1)
নামকরণ পাইপ ব্যবহার
বিকল্প পদ্ধতির মধ্যে অনেক গোপন সম্ভাবনা রয়েছে, নামী পাইপ হিসাবে পরিচিত এমন কিছু ব্যবহার করা ।
#!/bin/bash
mkfifo /tmp/namedPipe1 # this creates named pipe, aka fifo
# to make sure the shell doesn't hang, we run redirection
# in background, because fifo waits for output to come out
dialog --inputbox "This is an input box with named pipe" 40 40 2> /tmp/namedPipe1 &
# release contents of pipe
OUTPUT="$( cat /tmp/namedPipe1 )"
echo "This is the output " $OUTPUT
# clean up
rm /tmp/namedPipe1
বিকল্প পদ্ধতির সাহায্যে user.dz এর উত্তর সম্পর্কে আরও গভীরতর ওভারভিউ
ইউজার.ডিজেড দ্বারা মূল উত্তর এবং বাইটকম্যান্ডারের ব্যাখ্যা উভয়ই এটির একটি ভাল সমাধান এবং ওভারভিউ সরবরাহ করে। তবে, আমি বিশ্বাস করি যে এটি কেন কাজ করে তা ব্যাখ্যা করার জন্য একটি গভীর বিশ্লেষণ সুবিধাজনক হতে পারে ।
প্রথমত, দুটি বিষয় বোঝা গুরুত্বপূর্ণ: আমরা কী সমস্যাটি সমাধান করার চেষ্টা করছি এবং শেল প্রক্রিয়াগুলির অন্তর্নিহিত কাজগুলি যা আমরা পরিচালনা করছি। কাজ হ'ল কমান্ড প্রতিস্থাপনের মাধ্যমে একটি কমান্ডের আউটপুট ক্যাপচার করা। সরলতর পর্যালোচনার অধীনে যা সবাই জানেন, কমান্ডের বিকল্পগুলি stdout
একটি কমান্ড ক্যাপচার করে এবং অন্য কিছু দ্বারা এটি পুনরায় ব্যবহার করা যাক let এই ক্ষেত্রে, result=$(...)
অংশটি যে কোনও কমান্ড দ্বারা ...
ডাকা ভেরিয়েবলের দ্বারা নির্ধারিত হয় তার আউটপুট সংরক্ষণ করা উচিত result
।
হুডের নীচে, কমান্ড প্রতিস্থাপনটি আসলে পাইপ হিসাবে প্রয়োগ করা হয়, সেখানে একটি শিশু প্রক্রিয়া রয়েছে (আসল কমান্ড যা চালিত হয়) এবং পড়ার প্রক্রিয়া (যা আউটপুটকে ভেরিয়েবলে সংরক্ষণ করে)। এটি সিস্টেম কলগুলির একটি সহজ ট্রেস দিয়ে স্পষ্ট। লক্ষ্য করুন যে ফাইল বর্ণনাকারী 3 হ'ল পাইপের রিড প্রান্ত, এবং 4 লেখার শেষ। সন্তান প্রক্রিয়ার জন্য echo
যা এটির লিখেছেন stdout
- ফাইল বর্ণনাকারী 1, যে ফাইল বর্ণনাকারী আসলে ফাইল বর্ণনাকারী 4, যা পাইপের লেখ-এন্ড হয় কপি। লক্ষ্য করুন যে stderr
এখানে কোনও ভূমিকা পালন করছে না, কেবল এটি কেবল পাইপকে সংযুক্ত করার কারণে stdout
।
$ strace -f -e pipe,dup2,write,read bash -c 'v=$(echo "X")'
...
pipe([3, 4]) = 0
strace: Process 6200 attached
[pid 6199] read(3, <unfinished ...>
[pid 6200] dup2(4, 1) = 1
[pid 6200] write(1, "X\n", 2 <unfinished ...>
[pid 6199] <... read resumed> "X\n", 128) = 2
[pid 6200] <... write resumed> ) = 2
[pid 6199] read(3, "", 128) = 0
[pid 6200] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=6200, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++
আসুন এক সেকেন্ডের জন্য আসল উত্তরে ফিরে যাই। যেহেতু আমরা জানি যে dialog
টিউআই বাক্সটি লিখেছিল stdout
, এর জবাব দিয়েছে stderr
এবং কমান্ড প্রতিস্থাপনের মধ্যে stdout
অন্য কোথাও পাইপ দেওয়া হয়েছে, আমাদের ইতিমধ্যে সমাধানটির কিছু অংশ রয়েছে - আমাদের ফাইল বিবরণকারীকে এমনভাবে পুনর্বিবেচনা করা দরকার stderr
যা পাঠক প্রসেসে পাইপ করা হবে। এটি 2>&1
উত্তরের অংশ। তবে, টিউআই বাক্সটি দিয়ে আমরা কী করব?
ফাইল বর্ণনাকারী 3 এখানে আসে That's dup2()
সিস্কল আমাদের ফাইল বর্ণনাকারীদের নকল করতে দেয়, সেগুলি কার্যকরভাবে একই জায়গায় উল্লেখ করা যায়, তবুও আমরা তাদের আলাদাভাবে ম্যানিপুলেট করতে পারি। প্রসেসগুলির ফাইল বর্ণনাকারীগুলি যেগুলি নিয়ন্ত্রণ করে টার্মিনাল সংযুক্ত থাকে সেগুলি নির্দিষ্ট টার্মিনাল ডিভাইসে নির্দেশ করে। আপনি যদি এটি করেন তবে তা স্পষ্ট
$ ls -l /proc/self/fd
total 0
lrwx------ 1 user1 user1 64 Aug 20 10:30 0 -> /dev/pts/5
lrwx------ 1 user1 user1 64 Aug 20 10:30 1 -> /dev/pts/5
lrwx------ 1 user1 user1 64 Aug 20 10:30 2 -> /dev/pts/5
lr-x------ 1 user1 user1 64 Aug 20 10:30 3 -> /proc/6424/fd
/dev/pts/5
আমার বর্তমান সিউডো-টার্মিনাল ডিভাইসটি কোথায় । সুতরাং, আমরা যদি কোনওভাবে এই গন্তব্যটি সংরক্ষণ করতে পারি তবে আমরা টিউআইআই বক্সটি টার্মিনাল স্ক্রিনে লিখতে পারি। এটা কি exec 3>&1
করে। আপনি command > /dev/null
উদাহরণস্বরূপ পুনঃনির্দেশ সহ একটি কমান্ড কল করার সময় , শেল এটি স্টডআউট ফাইল বর্ণনাকারী পাস করে এবং তারপরে dup2()
সেই ফাইলটির বিবরণী লেখার জন্য ব্যবহার করে /dev/null
। exec
কমান্ড সঞ্চালিত কিছু অনুরূপdup2()
পুরো শেল সেশনের জন্য ফাইল বর্ণনাকারী, এইভাবে কোনো কমান্ড উত্তরাধিকারী ইতিমধ্যে পুনঃনির্দেশিত ফাইল বর্ণনাকারী করে। একই সঙ্গে exec 3>&1
। ফাইল বিবরণকারী 3
এখন নিয়ন্ত্রণকারী টার্মিনাল / পয়েন্ট উল্লেখ করবে এবং যে শেল সেশনে চালিত কোনও কমান্ড এটি সম্পর্কে জানতে পারবে know
সুতরাং যখন result=$(dialog --inputbox test 0 0 2>&1 1>&3);
ঘটবে, শেলটি ডায়ালগের জন্য লেখার জন্য একটি পাইপ তৈরি করে, তবে 2>&1
প্রথমে কমান্ডের ফাইল বিবরণকারীটিকে সেই পাইপের লিখিত ফাইল বর্ণনাকারীর উপর নকল করা যায় (এভাবে আউটপুটটি পাইপের প্রান্তে এবং ভেরিয়েবলটিতে পড়ে) ফাইল বর্ণনাকারী 1 এর 3 টি নকল হয়ে যাবে, এটি ফাইল বিবরণী 1 এখনও নিয়ন্ত্রণকারী টার্মিনালকে উল্লেখ করবে এবং টিইউআই ডায়ালগটি স্ক্রিনে প্রদর্শিত হবে।
এখন, আসলে প্রক্রিয়া, যা বর্তমান নিয়ন্ত্রণকারী টার্মিনাল জন্য একটি সংক্ষিপ্ত সরাসরি এর /dev/tty
। সুতরাং, ফাইল বর্ণনাকারী ব্যবহার না করে সমাধানটি সরল করা যায়, সহজভাবে:
result=$(dialog --inputbox test 0 0 2>&1 1>/dev/tty);
echo "$result"
মূল বিষয়গুলি মনে রাখবেন:
- ফাইল বিবরণকারী প্রতিটি কমান্ড দ্বারা শেল থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয়
- কমান্ড প্রতিস্থাপন পাইপ হিসাবে প্রয়োগ করা হয়
- সদৃশ ফাইল বর্ণনাকারী মূল স্থান হিসাবে একই স্থান উল্লেখ করবে, কিন্তু আমরা প্রতিটি ফাইল বর্ণনাকারী আলাদাভাবে ম্যানিপুলেট করতে পারি
আরো দেখুন
mktemp
একটি অস্থায়ী ফাইল তৈরি করতে কমান্ডটি ব্যবহার করতে পারেন ।