স্টাডাউট টার্মিনাল বা পাইপের সাথে সংযুক্ত থাকলে কোনও প্রোগ্রাম কীভাবে জানতে পারে?


12

সেগফাল্টিং প্রোগ্রামটি ডিবাগ করতে আমার সমস্যা হচ্ছে কারণ সেগফল্টের ঠিক আগে আউটপুটটি আমার যা প্রয়োজন তা হ'ল, তবে আমি যদি কোনও ফাইলে আউটপুট পাইপ করি তবে এটি হারিয়ে যায়। এই উত্তর অনুসারে: /unix//a/17339/22615 , কারণ প্রোগ্রামটির আউটপুট বাফারটি টার্মিনালের সাথে সংযুক্ত হওয়ার সাথে সাথেই ফ্লাশ হয় তবে কেবল পাইপের সাথে সংযুক্ত হলে নির্দিষ্ট পয়েন্টে at কয়েকটি প্রশ্ন এখানে:

  • একটি প্রোগ্রাম কীভাবে তার স্টাডাউটটি সংযুক্ত রয়েছে তা নির্ধারণ করে?

  • প্রোগ্রামটি কোনও টার্মিনালে লেখার সময় কীভাবে "স্ক্রিপ্ট" কমান্ড একই আচরণ করে?

  • স্ক্রিপ্ট কমান্ড ব্যতীত এটি কি অর্জন করা যায়?


সম্পর্কিত সম্পর্কিত প্রশ্ন হল unix.stackexchange.com/q/513926/5132
JdeBP

উত্তর:


23

কোনও ফাইল বর্ণনাকারী একটি টার্মিনাল ডিভাইসে নির্দেশ করে কিনা তা বলছে

কোনও প্রোগ্রাম জানাতে পারে যে কোনও ফাইল বর্ণনাকারী টিটি ডিভাইসের সাথে isatty()স্ট্যান্ডার্ড সি ফাংশন ব্যবহার করে জড়িত রয়েছে (যা সাধারণত নীচে একটি নির্দোষ টিটি-নির্দিষ্ট ioctl()সিস্টেম কল করে থাকে যখন এফডি টিটিটি ডিভাইসের দিকে ইঙ্গিত না করে ত্রুটি দিয়ে ফিরে আসবে) ।

[/ testউপযোগ তার সঙ্গে এটা করতে পারেন -tঅপারেটর।

if [ -t 1 ]; then
  echo stdout is open to a terminal
fi

জিএনইউ / লিনাক্স সিস্টেমে libc ফাংশন কলগুলি সন্ধান করা:

$ ltrace [ -t 1 ] | cat
[...]
isatty(1)                                      = 0
[...]

ট্র্যাকিং সিস্টেম কল:

$ strace [ -t 1 ] | cat
[...]
ioctl(1, TCGETS, 0x7fffd9fb3010)        = -1 ENOTTY (Inappropriate ioctl for device)
[...]

এটি একটি পাইপের দিকে নির্দেশ করে কিনা তা বলছে

কোনও এফডি পাইপ / ফিফোর সাথে যুক্ত কিনা তা নির্ধারণ করার জন্য, কেউ fstat()সিস্টেম কলটি ব্যবহার করতে পারে , যা st_modeএমন একটি কাঠামো ফিরিয়ে দেয় যার ক্ষেত্রটি সেই এফডিতে খোলার ফাইলের ধরণ এবং অনুমতি রয়েছে। S_ISFIFO()প্রমিত C ম্যাক্রো যে ব্যবহার করা যেতে পারে st_modeযদি FD একটি নল হয় / FIFO নির্ধারণ ক্ষেত্র।

এটি করতে পারে এমন কোনও স্ট্যান্ডার্ড ইউটিলিটি নেই fstat()তবে statকমান্ডের বেশ কয়েকটি বেমানান বাস্তবায়ন রয়েছে যা এটি করতে পারে। zshএর statঅন্তর্নির্মিত stat -sf "$fd" +modeযার সাহায্যে মোডটি স্ট্রিং প্রতিনিধিত্ব হিসাবে ফেরত দেয় যার প্রথম অক্ষরটি টাইপের ( pপাইপের জন্য) প্রতিনিধিত্ব করে । জিএনইউ এটির statসাহায্যে একই কাজ করতে পারে stat -c %A - <&"$fd"তবে কেবল stat -c %F - <&"$fd"এই ধরণের প্রতিবেদন করতে হবে। বিএসডি সহ stat: stat -f %St <&"$fd"বা stat -f %HT <&"$fd"

এটি সন্ধানযোগ্য কিনা তা বলছি

স্টাডাউট যদিও পাইপ হয় তবে অ্যাপ্লিকেশনগুলি সাধারণত যত্ন করে না। তারা যত্নশীল হতে পারে যে এটি সন্ধানযোগ্য (যদিও সাধারণত বাফার করবেন কিনা তা সিদ্ধান্ত নিতে হবে না)।

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

zshএবং ksh93শাঁস যদিও অপারেটার সচেষ্ট builtin আছে:

$ strace -e lseek ksh -c ': 1>#((CUR))' | cat
lseek(1, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
ksh: 1: not seekable
$ strace -e lseek zsh -c 'zmodload zsh/system; sysseek -w current -u 1 0 || syserror'
lseek(1, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
Illegal seek

বাফারিং অক্ষম করা হচ্ছে

scriptকমান্ড একটি প্রোগ্রাম আউটপুট ক্যাপচার করার জন্য সিউডো-টার্মিনাল যুগল ব্যবহার করে, তাই প্রোগ্রামের stdout- এ (এবং stdin এবং দ্বারা stderr) একটি সিউডো-টার্মিনাল ডিভাইস হতে হবে।

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

বাফারিং নিষ্ক্রিয় করার জন্য বিভিন্ন বিকল্প রয়েছে যা এখানে বেশ কয়েকটি প্রশ্নোত্তরে আলোচনা করা হয়েছে (যেমন আনবুফার বা এসডিবিউফ অনুসন্ধান করুন , কাট আউটপুট পুনর্নির্দেশ করা যায় না ) সিউডো-টার্মিনাল ব্যবহার করে socat/ script/ expect/ দ্বারা করা যেতে পারে unbuffer(একটি expectস্ক্রিপ্ট) / zshএর zptyবা জিএনইউ বা ফ্রিবিএসডি এর দ্বারা বাফারিং অক্ষম করতে এক্সিকিউটেবল কোড ইনজেকশন দিয়ে stdbuf


1
দুর্দান্ত উত্তর, এর জন্য আপনাকে অনেক ধন্যবাদ!
mowwwalker

অন্যটি, লিনাক্স-নির্দিষ্ট পদ্ধতির /procডিরেক্টরি হ'ল ডিরেক্টরি এবং প্রতিটি /proc/<integer>/ডিরেক্টরিতে /proc/<integer>/fd/ফাইল ডেস্ক্রিপ্টরের সন্ধান এবং সন্ধান করা যা pipefs সার্ভারসফল্ট / এএইচ / 833083৩০/৩6361111 তে একই আইড নম্বর রয়েছে তবে স্ক্রিপ্টগুলিতে এটি কেবল তখনই কার্যকর যখন কোনও বর্ণিত সিস্কল ব্যবহার করতে পারবেন না স্টিফেনের উত্তরে, এবং যথাযথ সমাধান আইএমএইচও-র চেয়ে অনেক বেশি কাজ
সের্গি কলডিয়াজহনি

বিএসডি- lseekতে, টার্মিনাল এবং অন্যান্য চরিত্রের ডিভাইসগুলিতে সাফল্য অর্জন করবে এবং প্রতিটি সফল পঠন () এ বাড়ানো একটি কাউন্টারকে কেবল পুনরায় / সেট করবে। এগুলি তাদের "সন্ধানযোগ্য" করে তোলে কিনা তা আমি জানি না।
মশভী

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