একটি বাশ শেল স্ক্রিপ্ট ধীর সূচনা কিভাবে প্রোফাইল করবেন?


124

আমার বাশ শেলটি শুরু হতে 3-4 সেকেন্ড সময় নেয়, আমি যদি এটি দিয়ে শুরু করি তবে --norcতা অবিলম্বে চলে।

আমি "প্রোফাইলিং" শুরু করেছি /etc/bash.bashrcএবং ~/.bashrcম্যানুয়ালি returnবিবৃতি andোকানো এবং গতি উন্নতির জন্য অনুসন্ধান করে, তবে এটি একটি পরিমাণগত প্রক্রিয়া নয় এবং এটি কার্যকর নয়।

আমি কীভাবে আমার বাশ স্ক্রিপ্টগুলি প্রোফাইল করতে পারি এবং কোন আদেশগুলি শুরু হতে বেশিরভাগ সময় নেয় তা দেখতে পারি?


3
আমি স্ক্রিপ্টগুলি প্রোফাইল করেছি এবং বেশিরভাগ সময় ব্যশ_কম্পলশন সেটআপ করার সময় ব্যয় হয়েছিল।
আন্দ্রেয়া স্পাডাক্সিনি 10

1
এটি দুর্দান্ত যেহেতু অবাক হওয়ার কিছু নেই pretty আপনি আপডেটগুলি জুড়ে আপনার পরিবর্তনগুলি বজায় রাখার সমস্যায় যেতে চাইলে আপনার প্রয়োজন হয় এমন অংশগুলি সরিয়ে আপনি গতি বাড়িয়ে দিতে পারেন
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া।

2
আপনি তুলনা করতে পারে: time bash -c 'exit'এবং time bash -i -c 'exit'সাথে পালন করতে পারে --norcএবং --noprofile
এফ। হাউরি

এই উত্তরটিও দেখুন (অস্বীকৃতি: এটি আমার)। আপনি যা যা বলছেন ঠিক তা নয়, তবে অবশ্যই সম্পর্কিত: unix.stackexchange.com/a/555510/384864
জোহান

উত্তর:


128

আপনার যদি জিএনইউ থাকে date(বা অন্য কোনও সংস্করণ যা ন্যানোসেকেন্ডগুলি আউটপুট দিতে পারে), শুরুতে এটি করুন /etc/bash.bashrc(বা আপনি যে কোনও বাস স্ক্রিপ্টে কোনও ট্রেস শুরু করতে চান):

PS4='+ $(date "+%s.%N")\011 '
exec 3>&2 2>/tmp/bashstart.$$.log
set -x

যোগ

set +x
exec 2>&3 3>&-

এর শেষে ~/.bashrc(বা কোনও বাশ স্ক্রিপ্টের বিভাগের শেষে আপনি থামতে চাইছেন) \011একটি অকট্যাল ট্যাব চরিত্র।

আপনার একটি ট্রেস লগ পাওয়া উচিত /tmp/bashstart.PID.logযা প্রতিটি কমান্ডের সেকেন্ডস.নোসেকেন্ডস টাইমস্ট্যাম্প কার্যকর করে। এক সময় থেকে পরের সময়ের মধ্যে পার্থক্য হ'ল মধ্যবর্তী পদক্ষেপটি যে পরিমাণ সময় নিয়েছিল।

আপনি জিনিসগুলি সঙ্কুচিত করার সাথে সাথে আপনি set -xপরে এবং set +xআগের দিকে যেতে (বা পছন্দসই বেশ কয়েকটি আগ্রহের অংশটি বন্ধন করতে পারেন)।

যদিও এটি জিএনইউর dateন্যানোসেকেন্ডের মতো সূক্ষ্ম-দানাদার নয় , বাশ ৫-এ একটি পরিবর্তনশীল রয়েছে যা মাইক্রোসেকেন্ডগুলিতে সময় দেয়। এটি ব্যবহার আপনাকে প্রতিটি লাইনের জন্য বহিরাগত এক্সিকিউটেবল তৈরি থেকে বাঁচায় এবং ম্যাক্স বা অন্য কোথাও জিএনইউ নেই এমন জায়গায় কাজ করে date- যতক্ষণ না আপনার কাছে বাশ 5 থাকে অবশ্যই। এর সেটিংটি পরিবর্তন করুন PS4:

PS4='+ $EPOCHREALTIME\011 '

@ পাওময়য়ের নির্দেশ অনুসারে, আপনার BASH_XTRACEFDযদি বাশ ৪.১ বা তার পরে থাকে তবে আপনি ট্রেসের আউটপুট একটি পৃথক ফাইল বর্ণনাকারীর কাছে প্রেরণ করতে পারেন । এই উত্তর থেকে :

#!/bin/bash

exec 5> command.txt
BASH_XTRACEFD="5"

echo -n "hello "

set -x
echo -n world
set +x

echo "!"

এটি ট্রেস আউটপুটটি ফাইলটি command.txtছেড়ে যাওয়ার stdoutএবং stdoutস্বাভাবিকভাবে আউটপুট হতে পারে (বা আলাদাভাবে পুনঃনির্দেশিত করা হবে)।


শেল প্রম্পটটি অদৃশ্য এবং আমার কমান্ডগুলি আবার প্রতিধ্বনিত হয় না এটাই কি স্বাভাবিক? যাইহোক, আমি ট্রেস পেয়েছি যাতে আমি বিশ্লেষণ শুরু করতে পারি .. অনেক অনেক ধন্যবাদ!
আন্ড্রেয়া স্পাডাকিনি 14

1
@ আন্ড্রেএসপ্যাডাকিনি: ফাইনালটি execএফডি 2 স্বাভাবিকের দিকে ফিরে আসে যাতে আপনার প্রম্পটটি ফিরে পাওয়া উচিত।
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

7
... আসলে ব্যাশ 4.2 সঙ্গে, এক ভালো কিছু করতে পারি - ব্যবহার \D{...}মধ্যে PS4অনুমতি দেয় সম্পূর্ণরূপে অবাধ সময় ফর্ম্যাট স্ট্রিং চালু কর্মক্ষমতা ওভারহেড ছাড়া সম্প্রসারিত করা dateএকটি subprocess হিসাবে।
চার্লস ডাফি 21

3
@ চার্লসডুফি: এগুলি উভয়ই দুর্দান্ত। তবে জিএনইউ dateবুঝতে পারে %Nএবং strftime(3)জিএনইউ সিস্টেমে বাশ ৪.২ দেয় না (কারণ তা নয়) - সীমাবদ্ধতার সাথে স্বেচ্ছাসেবী। পারফরম্যান্স বনাম রেজোলিউশন সম্পর্কে আপনার বক্তব্যটি একটি ভাল এবং ব্যবহারকারীর আঘাতটি কেবলমাত্র ডিবাগিংয়ের সময় (এবং শুধুমাত্র set -xকার্যকর হলে) অস্থায়ী তা মনে রাখবেন, ব্যবহারকারীকে বিজ্ঞতার সাথে পছন্দ করা উচিত ।
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

1
বাশ 4 এর সাথে, ডিবাগ আউটপুটটিকে ডিফল্টর (2, বা স্টডার) এর পরিবর্তে অন্য কোনও ফাইল বর্ণনকারীকে ডাইরেক্ট করতে BASH_XTRACEFD ভেরিয়েবল ব্যবহার করতে পারেন। এটি আউটপুট (প্রোফাইলিং ডেটা) বিশ্লেষণ করার সময় আসার সাথে সাথে প্রচুর পরিমাণে সহায়তা করে, কারণ স্ট্যাডার এবং সেট-এক্স আউটপুট আর সেট করতে হবে না (এত প্রান্তের কেস)।
পাওয়াময়

107

প্রোফাইলিং (4 টি উত্তর)

সম্পাদনা করুন: মার্চ 2016 যোগ scriptপদ্ধতি

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

4+ উত্তর আছে:

  • প্রথমটি @ ডেনিসউইলিয়ামসনের ধারণার উপর ভিত্তি করে তবে সংস্থান ব্যবহারের পরিমাণ অনেক কম
  • দ্বিতীয়টি আমার নিজস্ব ছিল (এর আগে;)
  • তৃতীয়টি @fgm উত্তরের ভিত্তিতে, তবে আরও সঠিক but
  • শেষ ব্যবহার script, scriptreplayএবং সময় ফাইল

  • শেষ পর্যন্ত পারফরম্যান্সের সাথে একটু তুলনা।

সীমিত কাঁটাচামচ ব্যবহার করে set -xএবং dateতবে

@ ডেনিস উইলিয়ামসনের ধারণাটি গ্রহণ করুন, তবে নিম্নলিখিত বাক্য গঠনের সাহায্যে কেবলমাত্র 3 টি কমান্ডের প্রাথমিক কাঁটাচামচ থাকবে:

exec 3>&2 2> >(tee /tmp/sample-time.$$.log |
                 sed -u 's/^.*$/now/' |
                 date -f - +%s.%N >/tmp/sample-time.$$.tim)
set -x

এটি করা dateকেবল একবারে চলবে । এটি কীভাবে কাজ করে তা দেখানোর জন্য একটি দ্রুত ডেমো / পরীক্ষা রয়েছে:

for i in {1..4};do echo now;sleep .05;done| date -f - +%N

নমুনা লিপি:

#!/bin/bash

exec 3>&2 2> >( tee /tmp/sample-$$.log |
                  sed -u 's/^.*$/now/' |
                  date -f - +%s.%N >/tmp/sample-$$.tim)
set -x

for ((i=3;i--;));do sleep .1;done

for ((i=2;i--;))
do
    tar -cf /tmp/test.tar -C / bin
    gzip /tmp/test.tar
    rm /tmp/test.tar.gz
done

set +x
exec 2>&3 3>&-

এই স্ক্রিপ্টটি চালিয়ে আপনি 2 টি ফাইল তৈরি করেন: /tmp/sample-XXXX.logএবং /tmp/sample-XXXX.tim(যেখানে XXXX স্ক্রিপ্ট চালানোর প্রক্রিয়া আইডি)।

আপনি এগুলি ব্যবহার করে উপস্থাপন করতে পারেন paste:

paste tmp/sample-XXXX.{tim,log}

অথবা আপনি বিভিন্ন সময় গণনা করতে পারেন:

paste <(
    while read tim ;do
        crt=000000000$((${tim//.}-10#0$last))
        printf "%12.9f\n" ${crt:0:${#crt}-9}.${crt:${#crt}-9}
        last=${tim//.}
      done < sample-time.24804.tim
  ) sample-time.24804.log 

 1388487534.391309713        + (( i=3 ))
 0.000080807        + (( i-- ))
 0.000008312        + sleep .1
 0.101304843        + (( 1 ))
 0.000032616        + (( i-- ))
 0.000007124        + sleep .1
 0.101251684        + (( 1 ))
 0.000033036        + (( i-- ))
 0.000007054        + sleep .1
 0.104013813        + (( 1 ))
 0.000026959        + (( i-- ))
 0.000006915        + (( i=2 ))
 0.000006635        + (( i-- ))
 0.000006844        + tar -cf /tmp/test.tar -C / bin
 0.022655107        + gzip /tmp/test.tar
 0.637042668        + rm /tmp/test.tar.gz
 0.000823649        + (( 1 ))
 0.000011314        + (( i-- ))
 0.000006915        + tar -cf /tmp/test.tar -C / bin
 0.016084482        + gzip /tmp/test.tar
 0.627798263        + rm /tmp/test.tar.gz
 0.001294946        + (( 1 ))
 0.000023187        + (( i-- ))
 0.000006845        + set +x

বা দুটি কলামে:

paste <(
    while read tim ;do
        [ -z "$last" ] && last=${tim//.} && first=${tim//.}
        crt=000000000$((${tim//.}-10#0$last))
        ctot=000000000$((${tim//.}-10#0$first))
        printf "%12.9f %12.9f\n" ${crt:0:${#crt}-9}.${crt:${#crt}-9} \
                                 ${ctot:0:${#ctot}-9}.${ctot:${#ctot}-9}
        last=${tim//.}
      done < sample-time.24804.tim
  ) sample-time.24804.log

রেন্ডার হতে পারে:

 0.000000000  0.000000000   + (( i=3 ))
 0.000080807  0.000080807   + (( i-- ))
 0.000008312  0.000089119   + sleep .1
 0.101304843  0.101393962   + (( 1 ))
 0.000032616  0.101426578   + (( i-- ))
 0.000007124  0.101433702   + sleep .1
 0.101251684  0.202685386   + (( 1 ))
 0.000033036  0.202718422   + (( i-- ))
 0.000007054  0.202725476   + sleep .1
 0.104013813  0.306739289   + (( 1 ))
 0.000026959  0.306766248   + (( i-- ))
 0.000006915  0.306773163   + (( i=2 ))
 0.000006635  0.306779798   + (( i-- ))
 0.000006844  0.306786642   + tar -cf /tmp/test.tar -C / bin
 0.022655107  0.329441749   + gzip /tmp/test.tar
 0.637042668  0.966484417   + rm /tmp/test.tar.gz
 0.000823649  0.967308066   + (( 1 ))
 0.000011314  0.967319380   + (( i-- ))
 0.000006915  0.967326295   + tar -cf /tmp/test.tar -C / bin
 0.016084482  0.983410777   + gzip /tmp/test.tar
 0.627798263  1.611209040   + rm /tmp/test.tar.gz
 0.001294946  1.612503986   + (( 1 ))
 0.000023187  1.612527173   + (( i-- ))
 0.000006845  1.612534018   + set +x

ব্যবহার trap debugএবং /proc/timer_listউপর সাম্প্রতিক জিএনইউ / লিনাক্স কার্নেল, ছাড়া কাটাচামচ

অধীনে জিএনইউ / লিনাক্স এর সাম্প্রতিক কার্নেল, আপনি একটি খুঁজে পেতে পারেন /procনামের ফাইল timer_list:

grep 'now at\|offset' /proc/timer_list
now at 5461935212966259 nsecs
  .offset:     0 nsecs
  .offset:     1383718821564493249 nsecs
  .offset:     0 nsecs

যেখানে বর্তমান সময়ের যোগফল 5461935212966259 + 1383718821564493249, তবে ন্যানোসেকেন্ডে।

সুতরাং অতিবাহিত সময়ের গণনার জন্য , অফসেট জানার দরকার নেই।

এই ধরণের কাজের জন্য, আমি elap.bash (V2) লিখেছিলাম , যা নিম্নলিখিত বাক্য গঠন দ্বারা উত্সাহিত করা হবে:

source elap.bash-v2

অথবা

. elap.bash-v2 init

(সম্পূর্ণ সিনট্যাক্সের জন্য মন্তব্য দেখুন)

সুতরাং আপনি কেবল আপনার স্ক্রিপ্টের শীর্ষে এই লাইনটি যুক্ত করতে পারেন:

. elap.bash-v2 trap2

সামান্য নমুনা:

#!/bin/bash

. elap.bash-v2 trap

for ((i=3;i--;));do sleep .1;done

elapCalc2
elapShowTotal \\e[1mfirst total\\e[0m

for ((i=2;i--;))
do
    tar -cf /tmp/test.tar -C / bin
    gzip /tmp/test.tar
    rm /tmp/test.tar.gz
done

trap -- debug
elapTotal \\e[1mtotal time\\e[0m

আমার হোস্টকে রেন্ডার করুন:

 0.000947481 Starting
 0.000796900 ((i=3))
 0.000696956 ((i--))
 0.101969242 sleep .1
 0.000812478 ((1))
 0.000755067 ((i--))
 0.103693305 sleep .1
 0.000730482 ((1))
 0.000660360 ((i--))
 0.103565001 sleep .1
 0.000719516 ((1))
 0.000671325 ((i--))
 0.000754856 elapCalc2
 0.316018113 first total
 0.000754787 elapShowTotal \e[1mfirst total\e[0m
 0.000711275 ((i=2))
 0.000683408 ((i--))
 0.075673816 tar -cf /tmp/test.tar -C / bin
 0.596389329 gzip /tmp/test.tar
 0.006565188 rm /tmp/test.tar.gz
 0.000830217 ((1))
 0.000759466 ((i--))
 0.024783966 tar -cf /tmp/test.tar -C / bin
 0.604119903 gzip /tmp/test.tar
 0.005172940 rm /tmp/test.tar.gz
 0.000952299 ((1))
 0.000827421 ((i--))
 1.635788924 total time
 1.636657204 EXIT

উত্স কমান্ডে যুক্তি হিসাবে trap2পরিবর্তে ব্যবহার করা trap:

#!/bin/bash

. elap.bash-v2 trap2
...

শেষ কমান্ড এবং মোট দুটি কলাম রেন্ডার করবে :

 0.000894541      0.000894541 Starting
 0.001306122      0.002200663 ((i=3))
 0.001929397      0.004130060 ((i--))
 0.103035812      0.107165872 sleep .1
 0.000875613      0.108041485 ((1))
 0.000813872      0.108855357 ((i--))
 0.104954517      0.213809874 sleep .1
 0.000900617      0.214710491 ((1))
 0.000842159      0.215552650 ((i--))
 0.104846890      0.320399540 sleep .1
 0.000899082      0.321298622 ((1))
 0.000811708      0.322110330 ((i--))
 0.000879455      0.322989785 elapCalc2
 0.322989785 first total
 0.000906692      0.323896477 elapShowTotal \e[1mfirst total\e[0m
 0.000820089      0.324716566 ((i=2))
 0.000773782      0.325490348 ((i--))
 0.024752613      0.350242961 tar -cf /tmp/test.tar -C / bin
 0.596199363      0.946442324 gzip /tmp/test.tar
 0.003007128      0.949449452 rm /tmp/test.tar.gz
 0.000791452      0.950240904 ((1))
 0.000779371      0.951020275 ((i--))
 0.030519702      0.981539977 tar -cf /tmp/test.tar -C / bin
 0.584155405      1.565695382 gzip /tmp/test.tar
 0.003058674      1.568754056 rm /tmp/test.tar.gz
 0.000955093      1.569709149 ((1))
 0.000919964      1.570629113 ((i--))
 1.571516599 total time
 0.001723708      1.572352821 EXIT

ব্যবহার strace

হ্যাঁ, straceকাজটি করতে পারতেন:

strace -q -f -s 10 -ttt sample-script 2>sample-script-strace.log

কিন্তু সেখানে প্রচুর জিনিস তৈরি করতে পারে!

wc sample-script-strace.log
    6925  57637 586518 sample-script-strace.log

আরও সীমাবদ্ধ কমান্ড ব্যবহার করে:

strace -f -s 10 -ttt -eopen,access,read,write ./sample-script 2>sample-script-strace.log

হালকা লগ ডাম্প করবে:

  4519  36695 374453 sample-script-strace.log

আপনি যা অনুসন্ধান করছেন তার উপর নির্ভর করে আপনি আরও সীমাবদ্ধ হতে পারেন:

 strace -f -s 10 -ttt -eaccess,open ./sample-script 2>&1 | wc
  189    1451   13682

সেগুলি পড়া কিছুটা কঠিন হবে:

{
    read -a first
    first=${first//.}
    last=$first
    while read tim line;do
        crt=000000000$((${tim//.}-last))
        ctot=000000000$((${tim//.}-first))
        printf "%9.6f %9.6f %s\n" ${crt:0:${#crt}-6}.${crt:${#crt}-6} \
            ${ctot:0:${#ctot}-6}.${ctot:${#ctot}-6} "$line"
        last=${tim//.}
      done
  } < <(
    sed </tmp/sample-script.strace -e '
        s/^ *//;
        s/^\[[^]]*\] *//;
        /^[0-9]\{4\}/!d
  ')

 0.000110  0.000110 open("/lib/x86_64-linux-gnu/libtinfo.so.5", O_RDONLY) = 4
 0.000132  0.000242 open("/lib/x86_64-linux-gnu/libdl.so.2", O_RDONLY) = 4
 0.000121  0.000363 open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY) = 4
 0.000462  0.000825 open("/dev/tty", O_RDWR|O_NONBLOCK) = 4
 0.000147  0.000972 open("/usr/lib/locale/locale-archive", O_RDONLY) = 4
 ...
 0.000793  1.551331 open("/etc/ld.so.cache", O_RDONLY) = 4
 0.000127  1.551458 open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY) = 4
 0.000545  1.552003 open("/usr/lib/locale/locale-archive", O_RDONLY) = 4
 0.000439  1.552442 --- SIGCHLD (Child exited) @ 0 (0) ---

আসল বাশ স্ক্রিপ্টটি এত সহজে অনুসরণ করা যায় না ...

ব্যবহার script, scriptreplayএবং সময়জ্ঞান ফাইল

বিএসডি ইউটিসগুলির অংশ হিসাবে , script(এবং scriptreplay) একটি খুব পুরানো সরঞ্জাম যা খুব কম পায়ের ছাপ সহ প্রোফাইল বাশকে ব্যবহার করতে ব্যবহৃত হতে পারে।

script -t script.log 2>script.tim -c 'bash -x -c "
    for ((i=3;i--;));do sleep .1;done

    for ((i=2;i--;)) ;do
        tar -cf /tmp/test.tar -C / bin
        gzip /tmp/test.tar
        rm /tmp/test.tar.gz
    done
"'

উত্পাদন করবে:

Script started on Fri Mar 25 08:29:37 2016
+ (( i=3 ))
+ (( i-- ))
+ sleep .1
+ (( 1 ))
+ (( i-- ))
+ sleep .1
+ (( 1 ))
+ (( i-- ))
+ sleep .1
+ (( 1 ))
+ (( i-- ))
+ (( i=2 ))
+ (( i-- ))
+ tar -cf /tmp/test.tar -C / bin
+ gzip /tmp/test.tar
+ rm /tmp/test.tar.gz
+ (( 1 ))
+ (( i-- ))
+ tar -cf /tmp/test.tar -C / bin
+ gzip /tmp/test.tar
+ rm /tmp/test.tar.gz
+ (( 1 ))
+ (( i-- ))
Script done on Fri Mar 25 08:29:39 2016

এবং দুটি ফাইল উত্পন্ন:

ls -l script.*
-rw-r--r-- 1 user user 450 Mar 25 08:29 script.log
-rw-r--r-- 1 user user 177 Mar 25 08:29 script.tim

ফাইল script.logসব ট্রেস থাকে এবং script.timহয় সময়জ্ঞান ফাইল :

head -n 4 script.*
==> script.log <==
Script started on Fri Mar 25 08:29:37 2016
+ (( i=3 ))
+ (( i-- ))
+ sleep .1

==> script.tim <==
0.435331 11
0.000033 2
0.000024 11
0.000010 2

আপনি লগফাইলের প্রথম এবং শেষ লাইন এবং / অথবা টাইমিং ফাইলের সময় সংক্ষিপ্ত করে মোট সময় নির্বাহ দেখতে পেলেন:

head -n1 script.log ;tail -n1 script.log 
Script started on Fri Mar 25 08:29:37 2016
Script done on Fri Mar 25 08:29:39 2016

sed < script.tim  's/ .*$//;H;${x;s/\n/+/g;s/^\+//;p};d' | bc -l
2.249755

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

scriptreplay script.{tim,log}

অথবা

scriptreplay script.{tim,log} 5

অথবা

 scriptreplay script.{tim,log} .2

পাশাপাশি সময় এবং আদেশগুলি দেখানোও আরও কিছুটা জটিল complex

exec 4<script.log
read -u 4 line
echo $line ;while read tim char;do
    read -u 4 -N $char -r -s line
    echo $tim $line
  done < script.tim &&
while read -u 4 line;do
    echo $line
done;exec 4<&-
Script started on Fri Mar 25 08:28:51 2016
0.558012 + (( i=3 ))
0.000053 
0.000176 + (( i-- ))
0.000015 
0.000059 + sleep .1
0.000015 
 + sleep .1) + (( 1 ))
 + sleep .1) + (( 1 ))
 + tar -cf /tmp/test.tar -C / bin
0.035024 + gzip /tmp/test.tar
0.793846 + rm /tmp/test.tar.gz
 + tar -cf /tmp/test.tar -C / bin
0.024971 + gzip /tmp/test.tar
0.729062 + rm /tmp/test.tar.gz
 + (( i-- )) + (( 1 ))
Script done on Fri Mar 25 08:28:53 2016

পরীক্ষা এবং উপসংহার

পরীক্ষা করার জন্য, আমি বাশ জটিল হ্যালো ওয়ার্ল্ডে দ্বিতীয় নমুনা ডাউনলোড করেছি , এই স্ক্রিপ্টটি আমার হোস্টে সম্পূর্ণ হতে প্রায় 0.72 সেকেন্ড সময় নেয়।

আমি এর একটিতে স্ক্রিপ্টের শীর্ষে যুক্ত করেছি:

  • elap.bashফাংশন দ্বারা

    #!/bin/bash
    
    source elap.bash-v2 trap2
    
    eval "BUNCHS=(" $(perl <<EOF | gunzip
    ...
  • দ্বারা set -xএবংPS4

    #!/bin/bash
    
    PS4='+ $(date "+%s.%N")\011 '
    exec 3>&2 2>/tmp/bashstart.$$.log
    set -x
    
    eval "BUNCHS=(" $(perl <<EOF | gunzip
    ...
  • দ্বারা set -xএবং প্রাথমিক কাঁটাচামনা দীর্ঘ নির্বাহ কমান্ড

    #!/bin/bash
    
    exec 3>&2 2> >(tee /tmp/sample-time.$$.log |
                     sed -u 's/^.*$/now/' |
                     date -f - +%s.%N >/tmp/sample-time.$$.tim)
    set -x
    
    eval "BUNCHS=(" $(perl <<EOF | gunzip
  • দ্বারা script(এবং set +x)

    script -t helloworld.log 2>helloworld.tim -c '
        bash -x complex_helloworld-2.sh' >/dev/null 

টাইমস

এবং কার্যকর করার সময়গুলি (আমার হোস্টে) তুলনা করুন:

  • সরাসরি 0.72 সেকেন্ড
  • elap.bash 13.18 সেকেন্ড
  • + পিএস 4 54.61 সেকেন্ড + তারিখ সেট করুন
  • সেট +1 কাঁটাচামচ 1.45 সেকেন্ড
  • স্ক্রিপ্ট এবং সময় ফাইল 2.19 সেকেন্ড
  • strace 4.47 সেকেন্ড

আউটপুট

  • elap.bashফাংশন দ্বারা

         0.000950277      0.000950277 Starting
         0.007618964      0.008569241 eval "BUNCHS=(" $(perl <<EOF | gunzi
         0.005259953      0.013829194 BUNCHS=("2411 1115 -13 15 33 -3 15 1
         0.010945070      0.024774264 MKey="V922/G/,2:"
         0.001050990      0.025825254 export RotString=""
         0.004724348      0.030549602 initRotString
         0.001322184      0.031871786 for bunch in "${BUNCHS[@]}"
         0.000768893      0.032640679 out=""
         0.001008242      0.033648921 bunchArray=($bunch)
         0.000741095      0.034390016 ((k=0))
  • দ্বারা set -xএবংPS4

    ++ 1388598366.536099290  perl
    ++ 1388598366.536169132  gunzip
    + 1388598366.552794757   eval 'BUNCHS=(' '"2411' 1115 -13 15 33 -3 15 1
    ++ 1388598366.555001983  BUNCHS=("2411 1115 -13 15 33 -3 15 13111 -6 1
    + 1388598366.557551018   MKey=V922/G/,2:
    + 1388598366.558316839   export RotString=
    + 1388598366.559083848   RotString=
    + 1388598366.560165147   initRotString
    + 1388598366.560942633   local _i _char
    + 1388598366.561706988   RotString=
  • দ্বারা set -xএবং প্রাথমিক কাঁটাচামনা দীর্ঘ নির্বাহ কমান্ড (এবং আমার দ্বিতীয় pasteনমুনা স্ক্রিপ্ট)

     0.000000000  0.000000000    ++ perl
     0.008141159  0.008141159    ++ gunzip
     0.000007822  0.008148981    + eval 'BUNCHS=(' '"2411' 1115 -13 15 33 -3 
     0.000006216  0.008155197    ++ BUNCHS=("2411 1115 -13 15 33 -3 15 13111 
     0.000006216  0.008161413    + MKey=V922/G/,2:
     0.000006076  0.008167489    + export RotString=
     0.000006007  0.008173496    + RotString=
     0.000006006  0.008179502    + initRotString
     0.000005937  0.008185439    + local _i _char
     0.000006006  0.008191445    + RotString=
  • দ্বারা strace

     0.000213  0.000213 brk(0)                = 0x17b6000
     0.000044  0.000257 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
     0.000047  0.000304 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faf1c0dc000
     0.000040  0.000344 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
     0.000040  0.000384 open("/etc/ld.so.cache", O_RDONLY) = 4
     ...
     0.000024  4.425049 close(10)             = 0
     0.000042  4.425091 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
     0.000028  4.425119 read(255, "", 4409)   = 0
     0.000058  4.425177 exit_group(0)         = ?
  • দ্বারা script

    Le script a débuté sur ven 25 mar 2016 09:18:35 CET
    0.667160 ++ gunzip
    0.000025 
    0.000948 ++ perl
    0.000011 
    0.005338 + eval 'BUNCHS=(' '"2411' 1115 -13 15 33 -3 15 13111 -6 1 111 4
    0.000044 1223 15 3311 121121 17 3311 121121 1223 3311 121121 17 3311 121
    0.000175 ++ BUNCHS=("2411 1115 -13 15 33 -3 15 13111 -6 15 1114 15 12211
    0.000029 1 1321 12211 412 21211 33 21211 -2 15 2311 11121 232 121111 122
    0.000023 4 3311 121121 12221 3311 121121 12221 3311 121121 1313 -6 15 33

উপসংহার

আমরা হব! যদি আমার খাঁটি বাশ প্রতিটি কমান্ডে ডেট করার চেয়ে দ্রুত হয় , তবে আমার খাঁটি বাশ প্রতিটি আদেশে কিছু ক্রিয়াকলাপ বোঝায়।

লগিং এবং সংরক্ষণের জন্য একটি স্বাধীন প্রক্রিয়া উত্সর্গ করার উপায় স্পষ্টতই আরও কার্যকর।

strace এটি একটি আকর্ষণীয় উপায়, আরও বিশদ, তবে পড়া শক্ত।

script, সহ scriptreplayএবং ত্বরণ ফ্যাক্টরটি খুব সুন্দর, প্রসেস এক্সিকিউশনের পরিবর্তে কনসোল এক্সচেঞ্জের উপর ভিত্তি করে এটির মতো নির্ভুলতা নয়, তবে খুব হালকা এবং দক্ষ (একই লক্ষ্য নয়, একই ব্যবহার নয়)।

পরিশেষে, আমি মনে করি যে পাঠযোগ্যতা এবং পারফরম্যান্সে আরও দক্ষ, set + 1 forkএই উত্তরটির প্রথমটি, তবে সুনির্দিষ্ট ক্ষেত্রে, নির্দিষ্ট ক্ষেত্রে নির্ভর করে আমি কিছু সময় straceএবং / বা scriptখুব বেশি ব্যবহার করি।



2
টাইমস অধ্যায় চমত্কার তথ্যপূর্ণ এবং ড্রাইভ বাড়িতে যে কাটাচামচ (স্ক্রিপ্টস এর প্রকৃতপক্ষে সম্পূর্ণভাবে উপর প্রভুত্ব বিস্তার অনেক ধরণের) এ হাঁচি কিছুই আছে। একটি ভাল (দীর্ঘ-টানা) উত্তরের জন্য +1। সম্ভবত ভবিষ্যতে আপনার আলাদা উত্তর পোস্ট বিবেচনা করা উচিত
sehe

1
অনেক ধন্যবাদ, @sehe! আপনি সেখানে একটি প্রস্তুত রেড টু-রান ব্যাশ উত্স ফাইলটি পাবেন: elap-bash-v3 (যার মধ্যে কিছু বৈশিষ্ট্য রয়েছে যেমন STDIN এবং STDERR এর স্বচ্ছ ব্যবহারের অনুমতি দেয় )
এফ

1
বাশ (> = 4.1) এর সাম্প্রতিক সংস্করণগুলিতে, আপনি এর exec {BASH_XTRACEFD}>পরিবর্তে exec 3>&2 2>যা করতে পারেন তার পরিবর্তে লগ ফাইলটি কেবল ট্রেস লগিং আউটপুট এবং অন্যান্য স্ট্যাডার আউটপুট দ্বারা পপুলেট করা যায়।
ws_e_c421

1
একক তারিখ প্রক্রিয়া পদ্ধতিতে এক্সিকিউটটি খুব চালাক এবং উপ-দ্বিতীয় নির্ভুলতার জন্য আমার পছন্দ pre এর জন্য script.sh, আমি কেবল bash -c "exec {BASH_XTRACEFD}> >(tee trace.log | sed -u 's/^.*$//' | date -f - +%s.%N > timing.log); set -x; . script.shপরিবর্তন না করে কেবল ডেটা এবং প্রোফাইলিং ডেটা পেতে পারি script.sh। যখন সাব-সেকেন্ড নির্ভুলতার প্রয়োজন হয় না, তখন আমি পছন্দ করি bash -c "exec {BASH_XTRACEFD}>trace.log; set -x; PS4='+\t'; . script.shযে সময়টি প্রতিটি ট্রেস লাইনের সাথে দ্বিতীয় যথার্থতার সাথে এবং তারিখের অজানা ছাড়াই (কম ওভারহেড) স্ট্যাম্প করে।
ws_e_c421

17

এটি প্রায়শই সিস্টেম কলগুলি সনাক্ত করতে সহায়তা করে

strace -c -f ./script.sh

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

-c প্রতিটি সিস্টেম কলের জন্য সময়, কল এবং ত্রুটিগুলি গণনা করুন এবং প্রোগ্রামটি থেকে বেরিয়ে আসার জন্য সারাংশের প্রতিবেদন করুন।

-ফলে শিশু প্রক্রিয়াগুলি সনাক্ত করুন ...

এটি আপনি যা চান ঠিক তা নয় এবং কোনও লাইন-ভিত্তিক প্রোফাইলার আপনাকে কী দেখায় তবে এটি সাধারণত গরম দাগগুলি খুঁজে পেতে সহায়তা করে।


5

আপনি DEBUG শর্ত trapসহ কমান্ডের উপর নজর রাখতে পারেন । আপনার আদেশগুলি সহ কার্যকর করার জন্য একটি আদেশ (গুলি) সেট করার একটি উপায় রয়েছে is উত্তরের নোটগুলি দেখুন।


@ ডেনিস উইলিয়ামসন: আমি এটি কিছুক্ষণ ব্যবহার করি নি, তবে আমার সিস্টেমের সহায়তায় বলা হয়েছে যে "যদি একটি সিগন্যাল_এসপেক ডিইবিইউজি হয়, প্রতিটি সাধারণ কমান্ডের পরে এআরজি কার্যকর করা হয়।"

বাশ ৪.০.৩৩ থেকে help trap: "যদি একটি সিগনাল_স্পেক ডিইবিইউজি হয়, প্রতিটি সাধারণ কমান্ডের আগে এআরজি কার্যকর করা হয়" " বাশ 3.2-এ, এটি "পরে" বলেছেন। এটি একটি টাইপো বাশ 2.05 বি হিসাবে, এটি আগে চালানো হয়েছিল। তথ্যসূত্র : "এই দস্তাবেজটিতে এই সংস্করণ, বাশ -২.০৫ বি-আলফা 1 এবং পূর্ববর্তী সংস্করণ, বাশ -২.০৫ এ-রিলিজের মধ্যে পরিবর্তনগুলি বিশদ রয়েছে ... ৩. বাশে নতুন বৈশিষ্ট্য ... ডাব্লু। ডিইবিইউজি ট্র্যাপটি এখন সরল কমান্ড, ((...)) কমান্ড, [[...]] শর্তাধীন কমান্ড এবং ((...)) লুপের আগে চালান । " প্রতিটি সংস্করণে পরীক্ষা করা নিশ্চিত করে যে এটি এর আগে
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

@ ডেনিস উইলিয়ামসন: ঠিক আছে, তবে আমার সেই সংস্করণটি রয়েছে। আমি উত্তরটি ঠিক করেছি :)

0

সময়, অ্যাক্ট্রেস, বাশ-এক্স set -xএবং set+x( http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html ) কোনও স্ক্রিপ্ট ডিবাগ করার জন্য গোঁড়া পথ থেকে যায়।

Neverteless আমাদের দিগন্ত বড় করার, এটা স্বাভাবিক লিনাক্স প্রোগ্রামের জন্য ডিবাগ এবং উপলব্ধ প্রোফাইলিং জন্য কিছু সিস্টেমের জন্য একটি চেক দিতে সম্ভব [এখানে তালিকার ONE] , যেমন এটা উপর ভিত্তি করে দরকারী একটি ফলাফল উচিত Valgrind বিশেষত ডিবাগ মেমরি বা sysprof প্রোফাইল পুরো সিস্টেম:

সিএসপ্রুফের জন্য:

সিএসপ্রুফের সাহায্যে আপনি আপনার মেশিনে চলমান সমস্ত অ্যাপ্লিকেশনকে মাল্টিথ্রেডেড বা মাল্টিপ্রসেসড অ্যাপ্লিকেশন সহ প্রোফাইল করতে পারেন ...

এবং সাব-প্রসেসগুলির শাখাটি নির্বাচন করার পরে যা আপনাকে আকর্ষণীয় বলে মনে হয়।


ভালগ্রিন্ডের জন্য:
আরও কিছু জিমের সাথে, মনে হয় সাধারণত কিছু বাইনারি (যেমন ওপেনঅফিস ) থেকে ইনস্টল করা কিছু প্রোগ্রাম ভালগ্রাইন্ডের কাছে দৃশ্যমান হওয়া সম্ভব ।

এটা তোলে থেকে পড়তে সম্ভব Valgrind এর প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী যে Valgrindপ্রোফাইলে হবে চাইল্ড প্রসেস যদি স্পষ্টভাবে অনুরোধ করা হয়েছে।

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

এটি সক্ষম এই বিকল্পটি দিয়ে এটি করবে

 --trace-children=yes 

অতিরিক্ত তথ্যসূত্র:


1
ডাউনভোটার নয়, তবে বেশিরভাগ টিপস, শীতল হলেও, এখানে প্রকৃতপক্ষে প্রাসঙ্গিক নয়। একটি উপযুক্ত প্রশ্ন জিজ্ঞাসা করা এবং এটি স্ব-উত্তর দেওয়া এখানে আরও স্বাগত — প্রাসঙ্গিক শিষ্টাচারের জন্য গুগল "স্ট্যাকওভারফ্লো স্ব-উত্তর"।
ব্লেজারব্ল্যাড

0

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

সুতরাং নিম্নলিখিত dtrace স্ক্রিপ্ট দেওয়া ( মূলsh_flowtime.d উপর ভিত্তি করে জিএইচ ):

#!/usr/sbin/dtrace -Zs
#pragma D option quiet
#pragma D option switchrate=10

dtrace:::BEGIN
{
        depth = 0;
        printf("%s %-20s  %-22s   %s %s\n", "C", "TIME", "FILE", "DELTA(us)", "NAME");
}

sh*:::function-entry
{
        depth++;
        printf("%d %-20Y  %-22s %*s-> %s\n", cpu, walltimestamp,
            basename(copyinstr(arg0)), depth*2, "", copyinstr(arg1));
}

sh*:::function-return
{
        printf("%d %-20Y  %-22s %*s<- %s\n", cpu, walltimestamp,
            basename(copyinstr(arg0)), depth*2, "", copyinstr(arg1));
        depth--;
}

sh*:::builtin-entry
{
        printf("%d %-20Y  %-22s %*s   > %s\n", cpu, walltimestamp,
            basename(copyinstr(arg0)), depth*2, "", copyinstr(arg1));
}

sh*:::command-entry
{
        printf("%d %-20Y  %-22s %*s   | %s\n", cpu, walltimestamp,
            basename(copyinstr(arg0)), depth*2, "", copyinstr(arg1));
}

আপনি ডেল্টা সময় সহ ফাংশন প্রবাহ ট্রেস করতে পারেন।

নমুনা আউটপুট:

# ./sh_flowtime.d
C TIME                  FILE                 DELTA(us)  -- NAME
0 2007 Aug 10 18:52:51  func_abc.sh                  0   -> func_a
0 2007 Aug 10 18:52:51  func_abc.sh                 54      > echo
0 2007 Aug 10 18:52:52  func_abc.sh            1022880      | sleep
0 2007 Aug 10 18:52:52  func_abc.sh                 34     -> func_b
0 2007 Aug 10 18:52:52  func_abc.sh                 44        > echo
0 2007 Aug 10 18:52:53  func_abc.sh            1029963        | sleep
0 2007 Aug 10 18:52:53  func_abc.sh                 44       -> func_c
0 2007 Aug 10 18:52:53  func_abc.sh                 43          > echo
0 2007 Aug 10 18:52:54  func_abc.sh            1029863          | sleep
0 2007 Aug 10 18:52:54  func_abc.sh                 33       <- func_c
0 2007 Aug 10 18:52:54  func_abc.sh                 14     <- func_b
0 2007 Aug 10 18:52:54  func_abc.sh                  7   <- func_a

তারপরে sort -nrk7কমান্ডটি ব্যবহার করে , আপনি বেশিরভাগ গ্রাহক কলগুলি দেখানোর জন্য আউটপুটটি বাছাই করতে পারেন।

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

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