পাইপ চেইনের মধ্যে জিকিউ ব্যবহার করা কোনও আউটপুট তৈরি করে না


12

jqআউটপুট পুনঃনির্দেশিত হওয়ার সময় একটি স্পষ্ট ফিল্টারের প্রয়োজনের বিষয়টি পুরো ওয়েবে আলোচিত। তবে আমি jqকোনও পাইপ চেইনের অংশ হলে আউটপুট পুনঃনির্দেশিত করতে অক্ষম , এমনকি যখন একটি স্পষ্ট ফিল্টার ব্যবহৃত হয়।

বিবেচনা:

touch in.txt
tail -f in.txt | jq '.f1'
# in a different terminal:
echo '{"f1":1,"f2":2}' >> in.txt
echo '{"f1":3,"f2":2}' >> in.txt

প্রত্যাশিত হিসাবে, jqকমান্ড থেকে মূল টার্মিনালের আউটপুট হল:

1
3

তবে আমি যদি jqকমান্ডের শেষে কোনও ধরণের পুনর্নির্দেশ বা পাইপিং যুক্ত করি তবে আউটপুটটি নিঃশব্দে যায়:

rm in.txt
touch in.txt
tail -f in.txt | jq '.f1' | tee out.txt
# in a different terminal:
echo '{"f1":1,"f2":2}' >> in.txt
echo '{"f1":3,"f2":2}' >> in.txt

প্রথম টার্মিনালে কোনও আউটপুট উপস্থিত হয় না এবং আউট.টিএসটি ফাঁকা থাকে।

আমি কয়েকশ প্রকারের চেষ্টা করেছি কিন্তু এটি একটি অধরা সমস্যা। আমি খুঁজে পেয়েছি যে একমাত্র কার্যকরী , mosquitto_subএবং থিংস নেটওয়ার্কের মাধ্যমে আবিষ্কার করা হয়েছে (এটি যেখানে আমি বিষয়টিও আবিষ্কার করেছি) হ'ল লেজ এবং জকিউ ফাংশনগুলি শেল স্ক্রিপ্টে মোড়ানো :

#!/bin/bash
tail -f $1 | while IFS='' read line; do
echo $line | jq '.f1'
done

তারপর:

./tail_and_jq.sh | tee out.txt
# in a different terminal:
echo '{"f1":1,"f2":2}' >> in.txt
echo '{"f1":3,"f2":2}' >> in.txt

এবং যথেষ্ট নিশ্চিত, আউটপুট প্রদর্শিত হবে:

1
3

এটি jqহোমব্রিউয়ের মাধ্যমে সর্বশেষতম ইনস্টল করা সহ :

$ echo $SHELL
/bin/bash
$ jq --version
jq-1.5
$ brew install jq
Warning: jq 1.5_3 is already installed and up-to-date

এটি কি jqপাইপ চেইনগুলির সাথে আমার বোঝার সাথে (মূলত অননুমোদিত) বাগ রয়েছে ?


1
এফডাব্লুআইডাব্লু আপনার tail -fকোনও প্রোগ্রামে অবিচ্ছিন্ন ইনপুট সরবরাহ করতে teeএবং আউটপুট প্রক্রিয়াজাতকরণের জন্য এখানে মোটামুটি (ভাল, কিছুটা) অদ্ভুত সেটআপ রয়েছে । আপনি যদি এখনও কোনও উত্তরের প্রয়োজনে থাকতেন তবে আমি চেইনটি সরল করার পরামর্শ দিয়েছিলাম <in.json jq '.f1' >out.jsonযাতে এটি কী কারণে ঘটছে তা আপনি সংকুচিত করতে পারেন।
ডেভিড জেড

আরও দেখুন বাশফাক # 9 - বাফারিং কী? বা, কেন আমার কমান্ড লাইন কোনও আউটপুট দেয় না:tail -f logfile | grep 'foo bar' | awk ...
চার্লস ডাফি

ভবিষ্যতের প্রচেষ্টার জন্য সমস্ত দুর্দান্ত পরামর্শ, আপনাকে ধন্যবাদ। এফডাব্লুআইডাব্লু, tailবিটটি পাইপটি ভেঙে ফেলার চেষ্টা করেছিল (প্রথম কমান্ডটি চালান, টিতে ফাইলটি পুনরায় ডাইরেক্ট করুন, টেল টু, নেক্সট কমান্ডে পাইপ করুন, ফাইলটিতে পুনঃনির্দেশ করুন, ইত্যাদি) এবং ধারাবাহিকভাবে এটি অবিচ্ছিন্নভাবে চালনা করুন। <যদিও মনে রাখতে হবে একটি ভাল টুল।
রাফারি

উত্তর:


20

jqএর স্ট্যান্ডার্ড আউটপুটটি পাইপ করা হলে আউটপুটটি বাফার হয়।

jqপ্রতিটি বস্তুর পরে তার আউটপুট বাফারটি ফ্লাশ করে দেওয়ার অনুরোধ করতে এর --unbufferedবিকল্পটি ব্যবহার করুন , যেমন

tail -f in.txt | jq --unbuffered '.f1' | tee out.txt

jqম্যানুয়াল থেকে :

--unbuffered

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


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

1
@ অ্যানডোরস্মেলিজিক সম্ভবত, বা আমাদের ইউনিটগুলিতে সমমানের ট্রেসিং ইউটিলিটি (নোট করুন যে ওপি হোমব্রিউ ব্যবহার করছে, যার অর্থ তারা ম্যাকোজে রয়েছে, এবং আমি ওপেনবিএসডি-তে রয়েছি, যার কোনটিরই এই লিনাক্স সরঞ্জাম নেই)। আর একটি সম্ভাবনা কেবল তা জানা যে আউটপুট বাফারিং কিছু নির্দিষ্ট পরিস্থিতিতে হতে পারে :-)
কুসালানন্দ

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

6

আপনি এখানে যা দেখছেন তা হ'ল ক্রিয়াকলাপে স্ট স্টিও বাফারিং। এটি একটি নির্দিষ্ট সীমা পর্যন্ত না পৌঁছা পর্যন্ত এটি বাফারে আউটপুট সংরক্ষণ করবে (512 বাইট বা 4KB বা এর চেয়ে বড় হতে পারে) এবং তারপরে এটি একবারে পাঠানো হবে।

এই স্ট্রাউটটি কোনও টার্মিনালের সাথে সংযুক্ত থাকলে এই বাফারিং স্বয়ংক্রিয়ভাবে অক্ষম হয়ে যায়, তবে যখন এটি কোনও পাইপের সাথে সংযুক্ত থাকে (যেমন আপনার ক্ষেত্রে) তখন এটি এই বাফারিং আচরণটি সক্ষম করে।

বাফারিং অক্ষম করার / নিয়ন্ত্রণ করার স্বাভাবিক উপায়টি setvbuf()ফাংশনটি ব্যবহার করছে ( আরও বিশদে এই উত্তরটি দেখুন) তবে এটি jqনিজের উত্স কোডে করা দরকার , তাই সম্ভবত আপনার পক্ষে ব্যবহারিক কিছু না ...

একটি কার্যবিধিত্ব আছে ... (একটি হ্যাক, কেউ বলতে পারে।) "আনবফার" নামে একটি প্রোগ্রাম রয়েছে, এটি "প্রত্যাশা" দিয়ে বিতরণ করা হয়েছে যা সিউডো-টার্মিনাল তৈরি করতে পারে এবং এটি একটি প্রোগ্রামের সাথে সংযুক্ত করতে পারে। সুতরাং, যদিও jqএখনও একটি পাইপে লিখতে হবে, এটি মনে করবে এটি কোনও টার্মিনালে লেখা হচ্ছে, এবং বাফারিং প্রভাবটি অক্ষম হয়ে যাবে।

"প্রত্যাশা" প্যাকেজটি ইনস্টল করুন, যা "আনবফার" এর সাথে উপস্থিত হওয়া উচিত, যদি আপনার কাছে ইতিমধ্যে এটি না থাকে ... উদাহরণস্বরূপ, ডেবিয়ান (বা উবুন্টু) এ:

$ sudo apt-get install expect

তারপরে আপনি এই আদেশটি ব্যবহার করতে পারেন:

$ tail -f in.txt | unbuffer -p jq '.f1' | tee out.txt

"আনবুফার" এর আরও কিছু তথ্যের জন্য এই উত্তরটি দেখুন , এবং আপনি এখানে একটি ম্যান পৃষ্ঠাও পেতে পারেন ।


আমি পছন্দ করি যে আপনি কেন পর্যবেক্ষণ আচরণটি ঘটে তা ব্যাখ্যা করেছেন, তবে কুসালানন্দ উল্লেখ করেছেন যে, jqস্থানীয়ভাবে অসমাপ্ত আউটপুট প্রয়োগ করা হয়েছে যাতে কর্মক্ষেত্রের প্রয়োজন নেই।
ডেভিড জেড

আহ খুব সুন্দর! আমি jqম্যান পৃষ্ঠায় সন্ধান করতে শুরু করি তবে কিছুক্ষণ পরে বিরক্ত হয়ে অন্য জিনিসগুলি করতে গিয়েছিলাম ... এমন কিছু আছে তা জেনে রাখা ভাল! :-)
ফিলাব্রেন্ডেন

1
প্রোটীপ, জিএনইউ কোর্টিলগুলি এলডিপ্রেডলয়েডের stdbuf -o0মাধ্যমে কোড ইনজেক্ট করবে এবং আপনার জন্য setvbuf()যাদু কল করবে। এটি ম্যাকোজে কাজ করে কিনা, আমি নিশ্চিত নই।
ব্যবহারকারী1686

1
যদিও expectMacOS উপর থেকেই ইনস্টল করা থাকে, unbufferনয়। তবে এটি হোমব্রিউ প্যাকেজের অংশ, তাই ম্যাকোগুলিও brew install expectকরবে।
রাফারি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.