বাশ স্ক্রিপ্ট এখনও চলমান অবস্থায় কোনও ফাইলে আউটপুট ফ্লাশিং জোর করে


90

আমার একটি ছোট স্ক্রিপ্ট রয়েছে, যা নিম্নোক্ত কমান্ডটি ব্যবহার করে ক্রন্টব দ্বারা প্রতিদিন বলা হয়:

/homedir/MyScript &> some_log.log

এই পদ্ধতির সমস্যাটি হ'ল কিছু_লগ.লগ কেবল মাইস্ক্রিপ্ট শেষ হওয়ার পরে তৈরি করা হবে। প্রোগ্রামটি চলমান অবস্থায় প্রোগ্রামটির আউটপুটটি ফাইলের মধ্যে ফ্লাশ করতে চাই যাতে আমি পছন্দ মতো কিছু করতে পারি

tail -f some_log.log

এবং অগ্রগতি ট্র্যাক রাখা, ইত্যাদি।


আপনার ছোট স্ক্রিপ্টটি ঠিক কী করে
ক্রিস্টোফেপ

7
পাইথন স্ক্রিপ্টগুলি আনফার করতে আপনি "পাইথন-ইউ" ব্যবহার করতে পারেন। পার্ল স্ক্রিপ্টগুলি আনফার করতে নীচে গ্রেগ হিউগিলের উত্তর দেখুন। এবং আরও ...
এলোইচি

আপনি যদি স্ক্রিপ্টটি সম্পাদনা করতে পারেন তবে আপনি সাধারণত একটি স্ক্রিপ্টের মধ্যে স্পষ্টভাবে আউটপুট বাফারটি ফ্লাশ করতে পারেন, উদাহরণস্বরূপ পাইথন সহ sys.stdout.flush()
ড্রেভিকো

উত্তর:


28

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


25
আমি সত্যিই এই উত্তর বুঝতে পারি না।
আলফোনসো সান্তিয়াগো

4
ভালো ধারণা কেন এই মত মান আউটপুট আচরণ করবে আউট চেক stackoverflow.com/a/13933741/282728 । একটি সংক্ষিপ্ত সংস্করণ default ডিফল্টরূপে, যদি কোনও ফাইলে পুনঃনির্দেশিত হয়, স্ট্ডআউট সম্পূর্ণরূপে বাফার হয়; এটি কেবলমাত্র ফ্লাশের পরে একটি ফাইলে লেখা আছে। স্ট্যাডার নয় — এটি প্রতি '\ n' এর পরে লেখা। একটি সমাধান হ'ল নীচে ব্যবহারকারীর দ্বারা প্রস্তাবিত 'স্ক্রিপ্ট' কমান্ডটি ব্যবহার করা উচিত 25858569, প্রতিটি লাইনের শেষের পরে স্টডআউট ফ্লাশ করা।
অ্যালেক্স

4
সুস্পষ্ট উল্লেখ করে এবং দশ বছর পরে, কিন্তু এটি একটি মন্তব্য নয়, কোনও উত্তর নয় এবং এটি গ্রহণযোগ্য উত্তর হওয়া উচিত নয়।
রিয়েলহ্যান্ডি

87

আমি এর সমাধান এখানে পেয়েছি । ওপির উদাহরণটি ব্যবহার করে আপনি মূলত চালান

stdbuf -oL /homedir/MyScript &> some_log.log

এবং তারপরে আউটপুট প্রতিটি লাইন পরে বাফার ফ্লাশ করা হয়। আমি প্রায়শই এটির সাথে nohupএক দূরবর্তী মেশিনে দীর্ঘ কাজ চালানোর জন্য একত্রিত করি ।

stdbuf -oL nohup /homedir/MyScript &> some_log.log

আপনি লগ আউট করার পরে এইভাবে আপনার প্রক্রিয়া বাতিল হবে না।


4
আপনি কিছু ডকুমেন্টেশনের জন্য একটি লিঙ্ক যুক্ত করতে পারেন stdbuf? এই মন্তব্যের ভিত্তিতে দেখে মনে হচ্ছে এটি কিছু ডিস্ট্রোজে উপলব্ধ নয়। আপনি কি স্পষ্ট করতে পারেন?
মনিকার লসুইট

4
stdbuf -o স্টডআউট বাফারিং সামঞ্জস্য করে। অন্যান্য বিকল্পগুলি হ'ল স্ট্যান্ডিন এবং স্টডারারের জন্য -i এবং -e। এল লাইনের বাফারিং সেট করে। কেউ বাফারিংয়ের জন্য বাফার আকার বা 0 টি নির্দিষ্ট করতে পারে।
সেপ্পো এনারভি

4
সেই লিঙ্কটি আর উপলব্ধ নেই।
জন-জোনস

4
@ নিক হার্টলি: stdbufজিএনইউ কোর্টিলের অংশ, নথিপত্রগুলি gnu.org- এ পাওয়া যাবে
থোর

যদি এটি যে কাউকে সহায়তা করে, ব্যবহার করুন export -f my_function এবং তারপরে আপনার stdbuf -oL bash -c "my_function -args"যদি কোনও স্ক্রিপ্টের পরিবর্তে কোনও ফাংশন চালানোর প্রয়োজন হয়
বেনামে

29
script -c <PROGRAM> -f OUTPUT.txt

কী -f। ম্যান স্ক্রিপ্ট থেকে উদ্ধৃতি:

-f, --flush
     Flush output after each write.  This is nice for telecooperation: one person
     does 'mkfifo foo; script -f foo', and another can supervise real-time what is
     being done using 'cat foo'.

ব্যাকগ্রাউন্ডে রান:

nohup script -c <PROGRAM> -f OUTPUT.txt

কি দারুন! একটি সমাধান যে কাজ করে busybox! (আমার শেলটি পরে জমাটবদ্ধ হয় তবে যাই হোক না কেন)
ভিক্টর সার্জিয়েনকো

9

আপনি teeফ্লাশিংয়ের প্রয়োজন ছাড়াই ফাইলটিতে লেখার জন্য ব্যবহার করতে পারেন ।

/homedir/MyScript 2>&1 | tee some_log.log > /dev/null

4
এটি এখনও কমপক্ষে আমার উবুন্টু 18.04 পরিবেশে আউটপুটটিকে বাফার করে। বিষয়বস্তুগুলি শেষ পর্যন্ত কোনওভাবেই ফাইলটিতে লিখিত হয়ে যায় তবে আমি মনে করি যে ওপি এমন একটি পদ্ধতি জিজ্ঞাসা করছে যেখানে তারা ফাইলটি লেখার সমাপ্তির আগে আরও নির্ভুলভাবে অগ্রগতি পর্যবেক্ষণ করতে পারে, এবং এই পদ্ধতিটি আউটপুট পুনঃনির্দেশের চেয়ে আর কোনও মঞ্জুরি দেয় না করে
mltsy

3

এটি কোনও ফাংশন নয় bash, যেহেতু সমস্ত শেলই প্রশ্নযুক্ত ফাইলটি খোলায় এবং তারপরে স্ক্রিপ্টের স্ট্যান্ডার্ড আউটপুট হিসাবে ফাইল বিবরণকারীটিকে পাস করে। আপনার যা করা দরকার তা নিশ্চিত হোন যে আপনার স্ক্রিপ্ট থেকে আপনার বারের তুলনায় আউটপুট আরও ঘন ঘন ঘন হয়েছে।

উদাহরণস্বরূপ পার্লে, সেটিংস স্থাপনের মাধ্যমে এটি সম্পাদন করা যেতে পারে:

$| = 1;

এই সম্পর্কে আরও তথ্যের জন্য পার্লওয়ার দেখুন ।


2

আপনার প্রোগ্রাম /homedir/MyScriptকীভাবে প্রয়োগ করা হয় তার উপর আউটপুট বাফারিং নির্ভর করে । যদি আপনি দেখতে পান যে আউটপুটটি বাফার হচ্ছে, আপনার প্রয়োগের জন্য আপনাকে এটি বাধ্য করতে হবে। উদাহরণস্বরূপ, পাইথন প্রোগ্রাম হলে sys.stdout.flush () ব্যবহার করুন বা এটি যদি সি প্রোগ্রাম থাকে তবে fflush (stdout) ব্যবহার করুন।


2

এই সাহায্য করবে?

tail -f access.log | stdbuf -oL cut -d ' ' -f1 | uniq 

এটি অবিলম্বে stdbuf ইউটিলিটি ব্যবহার করে access.log থেকে অনন্য এন্ট্রি প্রদর্শন করবে ।


একমাত্র সমস্যাটি হ'ল স্ট্ডবুফ মনে হচ্ছে কিছু পুরানো ইউটিলিটি যা নতুন ডিস্ট্রোজে উপলব্ধ নয়।
ওন্দ্রা Žižka

..আমার ব্যস্তবক্সে নেই :(
ক্যাম্পা

আসলে আমি stdbufউবুন্টুতে এই মুহুর্তে উপলব্ধ হয়েছি , কোথায় পেলাম তা নিশ্চিত নয়।
ওন্দ্রা Žižka

আমি সেন্টোস 7.5
সর্বাধিক

4
উবুন্টু 18.04 এ, stdbufএর অংশ coreutilus(এর সাথে পাওয়া গেছে apt-file search /usr/bin/stdbuf)।
রোমানো

1

এখানে সমস্যাটি কীভাবে চিহ্নিত হয়েছে তা হ'ল আপনাকে অপেক্ষা করতে হবে যে আপনি আপনার স্ক্রিপ্ট থেকে চালিত প্রোগ্রামগুলি তাদের কাজ শেষ করে।
যদি আপনার স্ক্রিপ্টে আপনি পটভূমিতে প্রোগ্রাম পরিচালনা করেন তবে আপনি আরও কিছু চেষ্টা করতে পারেন।

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

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

#!/bin/bash
#... some stuffs ...
program_1 &          # here you start a program 1 in background
PID_PROGRAM_1=${!}   # here you remember its PID
#... some other stuffs ... 
program_2 &          # here you start a program 2 in background
wait ${!}            # You wait it finish not really useful here
#... some other stuffs ... 
daemon_1 &           # We will not wait it will finish
program_3 &          # here you start a program 1 in background
PID_PROGRAM_3=${!}   # here you remember its PID
#... last other stuffs ... 
sync
wait $PID_PROGRAM_1
wait $PID_PROGRAM_3  # program 2 is just ended
# ...

যেহেতু waitচাকরির পাশাপাশি PIDসংখ্যাগুলির সাথে কাজ করে একটি অলস সমাধান হওয়া উচিত স্ক্রিপ্টের শেষে

for job in `jobs -p`
do
   wait $job 
done

পরিস্থিতি আরও কঠিন যদি আপনি এমন কিছু রান করেন যা ব্যাকগ্রাউন্ডে অন্য কিছু চালায় কারণ আপনাকে অনুসন্ধান করতে হবে এবং অপেক্ষা করতে হবে (যদি এটি হয় তবে) সমস্ত শিশুর প্রক্রিয়া শেষ : উদাহরণস্বরূপ আপনি যদি কোনও ডিমন চালান তবে সম্ভবত এটি ঘটবে না অপেক্ষা করার জন্য এটি শেষ :-)।

বিঃদ্রঃ:

  • অপেক্ষা $ {!} এর অর্থ "শেষ পটভূমি প্রক্রিয়াটি শেষ না হওয়া পর্যন্ত অপেক্ষা করুন" যেখানে $!সর্বশেষ পটভূমি প্রক্রিয়াটির পিআইডি is সুতরাং wait ${!}ঠিক পরে program_2 &রাখার সাথে program_2এটি ব্যাকগ্রাউন্ডে না পাঠিয়ে সরাসরি চালানো সমান equivalent&

  • এর সহায়তা থেকে wait:

    Syntax    
        wait [n ...]
    Key  
        n A process ID or a job specification
    

1

ধন্যবাদ @user3258569, স্ক্রিপ্ট সম্ভবত একমাত্র কাজ করে busybox!

যদিও শেলটি আমার পরে জমাট বাঁধছিল। কারণ অনুসন্ধানে, আমি এই বড় লাল সতর্কতাগুলি স্ক্রিপ্ট ম্যানুয়াল পৃষ্ঠাতে "একটি অ-ইন্টারেক্টিভ শেলগুলিতে ব্যবহার করবেন না" :

scriptপ্রাথমিকভাবে ইন্টারেক্টিভ টার্মিনাল সেশনের জন্য ডিজাইন করা হয়েছে। যখন স্টিডিন কোনও টার্মিনাল নয় (উদাহরণস্বরূপ echo foo | script:), তখন সেশনটি স্তব্ধ হয়ে যেতে পারে, কারণ স্ক্রিপ্ট সেশনের মধ্যে ইন্টারেক্টিভ শেল ইওএফকে মিস করে এবং scriptসেশনটি বন্ধ করার সময় কোনও ক্লু থাকে না। দেখুন নোটস আরও তথ্যের জন্য অধ্যায়।

সত্য। script -c "make_hay" -f /dev/null | grep "needle"আমার জন্য খোল জমে ছিল।

সতর্কবার্তা হিসাবে গণ্য, আমি ভেবেছিলাম যে echo "make_hay" | scriptএকটি ইওএফ পাস করবে, তাই আমি চেষ্টা করেছিলাম

echo "make_hay; exit" | script -f /dev/null | grep 'needle'

এবং এটা কাজ করে!

ম্যান পৃষ্ঠাতে সতর্কতা নোট করুন। এটি আপনার পক্ষে কাজ নাও করতে পারে।


0

স্টাডবুফের বিকল্প হ'ল awk '{print} END {fflush()}' আমি ইচ্ছা করি এটি করার জন্য কোনও ব্যাশ অন্তর্নির্মিত ছিল। সাধারণত এটি প্রয়োজনীয় হওয়া উচিত নয়, তবে পুরানো সংস্করণগুলির সাথে ফাইল বর্ণনকারীগুলিতে বাশ সিঙ্ক্রোনাইজেশন বাগ থাকতে পারে।


-2

আমি জানি না এটি কাজ করবে কিনা তবে কল করার syncকী আছে?


4
syncনিম্ন-স্তরের ফাইল সিস্টেম অপারেশন এবং অ্যাপ্লিকেশন পর্যায়ে বাফার আউটপুট সম্পর্কিত নয়।
গ্রেগ হিউগিল

4
syncপ্রয়োজনে কোনও নোংরা ফাইল সিস্টেম বাফারগুলিকে শারীরিক স্টোরেজে লেখায়। এটি ওএসের অভ্যন্তরীণ; ওএসের শীর্ষে চলমান অ্যাপ্লিকেশনগুলি সর্বদা ডিস্ক ব্লকগুলি শারীরিক স্টোরেজে লিখিত হয়েছে কিনা তা ফাইল সিস্টেমের একটি সুসংগত দৃশ্য দেখতে পায়। মূল প্রশ্নের জন্য, অ্যাপ্লিকেশন (স্ক্রিপ্ট) সম্ভবত আবেদনের অভ্যন্তরীণ কোনও বাফারে আউটপুট বাফার করছে, এবং ওএস এমনকি এখনও জানতে পারে না (আউটপুট) আসলে আউটপুটটি স্টাডআউটে লেখা হবে। সুতরাং একটি অনুমান "সিঙ্ক" টাইপ অপারেশন স্ক্রিপ্টের "পৌঁছন" করতে সক্ষম হবে না এবং ডেটা টেনে আনবে।
গ্রেগ হিউগিল

-2

ম্যাক ওএস এক্স এর ব্যাকগ্রাউন্ড প্রক্রিয়াটি নিয়ে আমার এই সমস্যা হয়েছিল StartupItems। আমি এটিই এভাবে সমাধান করি:

আমি যদি তৈরি sudo ps auxকরি তবে তা দেখতে পাচ্ছি mytoollaunched

আমি খুঁজে পেয়েছি যে (বাফারিংয়ের কারণে) যখন ম্যাক ওএস এক্স বন্ধ হয়ে যায় তখন mytoolকখনই আউটপুটটি sedকমান্ডে স্থানান্তর করে না । যাইহোক, যদি আমি চালানো sudo killall mytool, তারপর mytoolআউটপুট স্থানান্তর sedকমান্ড। সুতরাং, আমি ম্যাক ওএস এক্স বন্ধ হয়ে গেলে মৃত্যুদন্ড কার্যকর stopকরা হয় StartupItemsএমন একটি কেস যুক্ত করেছি :

start)
    if [ -x /sw/sbin/mytool ]; then
      # run the daemon
      ConsoleMessage "Starting mytool"
      (mytool | sed .... >> myfile.txt) & 
    fi
    ;;
stop)
    ConsoleMessage "Killing mytool"
    killall mytool
    ;;

এটি আপনার পরিবেশের সাথে অত্যন্ত নির্দিষ্ট হওয়ায় এটি ফ্রিম্যান সত্যিই একটি ভাল উত্তর নয়। ওপি আউটপুটটিকে এটি হত্যা না করে পর্যবেক্ষণ করতে চায়।
ধুসর

-3

ভাল এটি পছন্দ করুন বা এটি পুনর্নির্দেশ কাজ করে না।

আপনার ক্ষেত্রে আপনার স্ক্রিপ্টের আউটপুট (যার অর্থ আপনার স্ক্রিপ্ট শেষ হয়েছে) সেই ফাইলটিতে পুনঃনির্দেশিত।

আপনি যা করতে চান তা হ'ল আপনার স্ক্রিপ্টে সেইগুলি পুনর্নির্দেশগুলি যুক্ত করা।

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