كيفية قمع الرسالة المنتهية بعد القتل في باش؟

StackOverflow https://stackoverflow.com/questions/81520

  •  09-06-2019
  •  | 
  •  

سؤال

كيف يمكنك قمع Terminated الرسالة التي تظهر بعد قتل عملية في نص باش؟

حاولت set +bm, ، ولكن هذا لا يعمل.

أعلم أن الحل الآخر يتضمن الاتصال exec 2> /dev/null, ، ولكن هل هذا موثوق؟كيف يمكنني إعادة تعيينه مرة أخرى حتى أتمكن من الاستمرار في رؤية stderr؟

هل كانت مفيدة؟

المحلول

الجواب القصير هو أنك لا تستطيع ذلك.يقوم Bash دائمًا بطباعة حالة المهام الأمامية.تنطبق علامة المراقبة فقط على وظائف الخلفية، وعلى الأصداف التفاعلية فقط، وليس على البرامج النصية.

راجع notify_of_job_status() في jobs.c.

كما قلت، يمكنك إعادة التوجيه بحيث يشير الخطأ القياسي إلى /dev/null ولكن بعد ذلك تفوت أي رسائل خطأ أخرى.يمكنك جعله مؤقتًا عن طريق إجراء إعادة التوجيه في غلاف فرعي يقوم بتشغيل البرنامج النصي.وهذا يترك البيئة الأصلية وحدها.

(script 2> /dev/null)

والذي سيفقد جميع رسائل الخطأ، ولكن فقط من هذا البرنامج النصي، وليس من أي شيء آخر يتم تشغيله في تلك الصدفة.

يمكنك حفظ الخطأ القياسي واستعادته عن طريق إعادة توجيه واصف ملف جديد للإشارة إلى هناك:

exec 3>&2          # 3 is now a copy of 2
exec 2> /dev/null  # 2 now points to /dev/null
script             # run script with redirected stderr
exec 2>&3          # restore stderr to saved
exec 3>&-          # close saved version

لكنني لا أوصي بهذا - الجانب الإيجابي الوحيد من الأول هو أنه يحفظ استدعاء الصدفة الفرعية، في حين أنه أكثر تعقيدًا، وربما يغير سلوك البرنامج النصي، إذا قام البرنامج النصي بتغيير واصفات الملف.


يحرر:

للحصول على إجابة أكثر ملاءمة، تحقق من الإجابة المقدمة بواسطة مارك إدغار

نصائح أخرى

لكي تقوم بإسكات الرسالة، يجب أن تقوم بإعادة التوجيه stderr في الوقت الذي يتم فيه إنشاء الرسالة.بسبب ال kill يرسل الأمر إشارة ولا ينتظر استجابة العملية المستهدفة وإعادة التوجيه stderr التابع kill الأمر لا ينفعك.بنيت باش wait تم صنعه خصيصًا لهذا الغرض.

فيما يلي مثال بسيط جدًا يقضي على أحدث أمر في الخلفية.(اعرف المزيد عن $!هنا.)

kill $!
wait $! 2>/dev/null

لأن كلاهما kill و wait قبول معرفات متعددة (PIDs)، ويمكنك أيضًا إجراء عمليات قتل جماعية.فيما يلي مثال يقتل جميع العمليات الخلفية (للعملية/البرنامج النصي الحالي بالطبع).

kill $(jobs -rp)
wait $(jobs -rp) 2>/dev/null

لقد تم قيادتي إلى هنا من سحق:قتل عملية وظيفة الخلفية بصمت.

مستوحاة من إجابة مارس.كنت أستخدم kill -INT كما يقترح مع بعض النجاح، لكنني لاحظت أنه لم يقتل بعض العمليات.بعد اختبار بعض الإشارات الأخرى أرى ذلك SIGPIPE سوف يقتل كذلك بدون رسالة.

kill -PIPE

أو ببساطة

kill -13

حل:استخدم SIGINT (يعمل فقط في الأصداف غير التفاعلية)

العرض التوضيحي:

cat > silent.sh <<"EOF"
sleep 100 &
kill -INT $!
sleep 1
EOF

sh silent.sh

http://thread.gmane.org/gmane.comp.shells.bash.bugs/15798

ربما يتم فصل العملية عن عملية الصدفة الحالية عن طريق الاتصال disown?

هل هذا ما نبحث عنه جميعا؟

غير مرغوب فيه:

$ sleep 3 &
[1] 234
<pressing enter a few times....>
$
$
[1]+  Done                    sleep 3
$

مطلوب:

$ (set +m; sleep 3 &)
<again, pressing enter several times....>
$
$
$
$
$

كما ترون، لا توجد رسالة نهاية المهمة.يناسبني أيضًا نصوص bash، وأيضًا لعمليات الخلفية المقتولة.

يؤدي "set +m" إلى تعطيل التحكم في الوظيفة (راجع "مجموعة المساعدة") للغلاف الحالي.لذا، إذا قمت بإدخال الأمر الخاص بك في غلاف فرعي (كما هو الحال هنا بين قوسين)، فلن تؤثر على إعدادات التحكم في الوظيفة الخاصة بالصدفة الحالية.العيب الوحيد هو أنك تحتاج إلى إعادة معرف عملية الخلفية الخاصة بك إلى الصدفة الحالية إذا كنت تريد التحقق مما إذا كانت قد انتهت، أو تقييم رمز الإرجاع.

هناك طريقة أخرى لتعطيل إشعارات الوظائف وهي وضع أمرك في الخلفية في ملف sh -c 'cmd &' بناء.

#!/bin/bash
# ...
pid="`sh -c 'sleep 30 & echo ${!}' | head -1`"
kill "$pid"
# ...

# or put several cmds in sh -c '...' construct
sh -c '
sleep 30 &
pid="${!}"
sleep 5 
kill "${pid}"
'

يعمل هذا أيضًا مع killall (لأولئك الذين يفضلونه):

killall -s SIGINT (yourprogram) 

يحجب الرسالة...كنت أقوم بتشغيل mpg123 في وضع الخلفية.لا يمكن قتله بصمت إلا عن طريق إرسال ctrl-c (SIGINT) بدلاً من SIGTERM (افتراضي).

لقد فعل التنصل الشيء الصحيح تمامًا بالنسبة لي - يعد exec 3>&2 محفوفًا بالمخاطر لعدة أسباب - يبدو أن set +bm لا يعمل داخل البرنامج النصي، فقط في موجه الأوامر

لقد نجحت في إضافة "jobs 2>&1 >/dev/null' إلى البرنامج النصي، لست متأكدًا مما إذا كان سيساعد البرنامج النصي لأي شخص آخر، ولكن إليك عينة.

    while true; do echo $RANDOM; done | while read line
    do
    echo Random is $line the last jobid is $(jobs -lp)
    jobs 2>&1 >/dev/null
    sleep 3
    done

لقد وجدت أن وضع أمر القتل في إحدى الوظائف ثم وضع الخلفية للوظيفة يمنع إخراج الإنهاء

function killCmd() {
    kill $1
}

killCmd $somePID &

بسيط:

{ kill $! } 2>/dev/null

ميزة؟يمكن استخدام أي إشارة

السابق:

{ kill -9 $PID } 2>/dev/null
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top