باش لا محاصرة المقاطعات خلال رسينك / سوبشيل إكسيك البيانات

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

سؤال

السياق:

لدي برنامج نصي باش يحتوي على سوبشيل وفخ للخروج بسيودوسينال ، وانها ليست محاصرة بشكل صحيح المقاطعات خلال rsync.هنا مثال:

#!/bin/bash
logfile=/path/to/file;
directory1=/path/to/dir
directory2=/path/to/dir

cleanup () {
     echo "Cleaning up!"
     #do stuff
     trap - EXIT 
}

trap '{
    (cleanup;) | 2>&1 tee -a $logfile
}' EXIT

(
    #main script logic, including the following lines:
    (exec sleep 10;);        
    (exec rsync --progress -av --delete $directory1 /var/tmp/$directory2;);

)  | 2>&1 tee -a $logfile
trap - EXIT #just in case cleanup isn't called for some reason

فكرة البرنامج النصي هو هذا:يعمل معظم المنطق المهم في غلاف فرعي يتم نقله عبر الأنابيب tee وإلى ملف السجل ، لذلك أنا لم يكن لديك ل tee كل سطر واحد من المنطق الرئيسي للحصول على كل شيء تسجيل.كلما ينتهي سوبشيل ، أو يتم إيقاف البرنامج النصي لأي سبب من الأسباب (خروج بسيودوسينال يجب التقاط كل هذه الحالات) ، فإن فخ اعتراض عليه وتشغيل cleanup() وظيفة ، ومن ثم إزالة الفخ.ال rsync و sleep يتم تشغيل الأوامر (النوم هو مجرد مثال) من خلال exec لمنع إنشاء عمليات الزومبي إذا قمت بقتل البرنامج النصي الأصل أثناء تشغيله ، ويتم لف كل أمر يحتمل أن يكون طويل الأمد في غلاف فرعي خاص به بحيث عندما exec ينتهي ، لن ينهي البرنامج النصي بأكمله.

المشكلة:

إذا قمت بمقاطعة البرنامج النصي (عبر kill أو السيطرة + ج) خلال إكسيك / سوبشيل ملفوفة sleep الأمر ، فخ يعمل بشكل صحيح ، وأرى "تنظيف!"ردد وتسجيل.إذا كنت يقطع البرنامج النصي خلال rsync القيادة ، أرى rsync النهاية ، والكتابة rsync error: received SIGINT, SIGTERM, or SIGHUP (code 20) at rsync.c(544) [sender=3.0.6] إلى الشاشة ، ثم يموت البرنامج النصي فقط;لا تنظيف ، لا محاصرة.لماذا لا مقاطعة / قتل rsync تحريك الفخ?

لقد حاولت استخدام --no-detach التبديل مع رسينك ، لكنه لم يغير أي شيء.لدي باش 4.1.2 ، رسينك 3.0.6 ، سينتوس 6.2.

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

المحلول

ماذا عن مجرد إعادة توجيه كل الإخراج من النقطة س إلى نقطة الإنطلاق دون الحاجة إلى تكراره في كل مكان والفوضى مع جميع الأصداف الفرعية والمديرين التنفيذيين ...(آمل ألا أفتقد شيئا)

#!/bin/bash
logfile=/path/to/file;
directory1=/path/to/dir
directory2=/path/to/dir

exec > >(exec tee -a $logfile) 2>&1

cleanup () {
     echo "Cleaning up!"
     #do stuff
     trap - EXIT 
}
trap cleanup EXIT

sleep 10
rsync --progress -av --delete $directory1 /var/tmp/$directory2

نصائح أخرى

بالإضافة إلى set -e, ، أعتقد أنك تريد set -E:

إذا تم تعيينه ، يتم توريث أي فخ على خطأ من قبل وظائف شل ، واستبدال الأوامر ، والأوامر المنفذة في بيئة قذيفة فرعية.عادة لا يتم توريث فخ الخطأ في مثل هذه الحالات.

بدلا من ذلك ، بدلا من التفاف الأوامر الخاصة بك في سوبشيلز استخدام الأقواس المتعرجة التي سوف لا تزال تعطيك القدرة على إعادة توجيه مخرجات الأمر ولكن سيتم تنفيذها في قذيفة الحالية.

سيتم القبض على إنتيروبت بشكل صحيح إذا قمت بإضافة إنت إلى فخ

trap '{
    (cleanup;) | 2>&1 tee -a $logfile
}' EXIT INT

باش محاصرة المقاطعات بشكل صحيح.ومع ذلك ، هذا لا يجيب على السؤال ، لماذا الفخاخ النصي على الخروج إذا sleep هو إنتيروبتد ، ولا لماذا لا يؤدي على rsync, ، ولكن يجعل البرنامج النصي يعمل كما هو مفترض.نأمل أن يساعد هذا.

قد يتم تكوين قذيفة للخروج على الخطأ:

bash # enter subshell
set -e
trap "echo woah" EXIT
sleep 4

إذا كنت تقاطع sleep (^ج) ثم سيخرج الغلاف الفرعي بسبب set -e و طباعة woah في هذه العملية.

أيضا ، لا علاقة لها قليلا:الخاص بك trap - EXIT هو في سوبشيل (صراحة) ، لذلك لن يكون لها تأثير بعد عودة وظيفة التنظيف

من الواضح جدا من التجربة أن rsync يتصرف مثل الأدوات الأخرى مثل ping ولا ترث إشارات من الوالد باش الدعوة.

لذلك عليك أن تكون مبدعا قليلا في هذا وأن تفعل شيئا مثل ما يلي:

$ cat rsync.bash
#!/bin/sh

 set -m
 trap '' SIGINT SIGTERM EXIT
 rsync -avz LargeTestFile.500M root@host.mydom.com:/tmp/. &
 wait

 echo FIN

الآن عندما أقوم بتشغيله:

$ ./rsync.bash
X11 forwarding request failed
building file list ... done
LargeTestFile.500M
^C^C^C^C^C^C^C^C^C^C
sent 509984 bytes  received 42 bytes  92732.00 bytes/sec
total size is 524288000  speedup is 1027.96
FIN

ويمكننا أن نرى الملف لم نقل بالكامل:

$ ll -h | grep Large
-rw-------. 1  501 games 500M Jul  9 21:44 LargeTestFile.500M

كيف يعمل

الحيلة هنا هي أننا نقول باش عبر set -m لتعطيل عناصر التحكم في الوظيفة على أي وظائف خلفية داخلها.نحن ثم الخلفية rsync ثم تشغيل wait الأمر الذي سينتظر على أمر التشغيل الأخير, rsync, ، حتى يكتمل.

نحن ثم حراسة السيناريو بأكمله مع trap '' SIGINT SIGTERM EXIT.

المراجع

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top