/bin/sh
私は最初にいくつかのCVSリポジトリのローカルコピーをに更新し、次に私のコンピュータからチェックrsync
アウトされたバージョンを更新するこのようなスクリプト(OpenBSDに書かれています)を持っています。このスクリプトは OpenBSD 経由で root として実行されます。doas
(sudo
OpenBSDの「同等」):
#!/bin/sh
int_handler () {
echo 'Wait...' >&2
quit=1
}
quit=0
trap int_handler INT
for r in CVSROOT src xenocara ports; do
su cvsuser -c 'rsync --archive --itemize-changes --delete --omit-dir-times \
"rsync://anoncvs.eu.openbsd.org/OpenBSD-cvs/$r/" \
"/extra/cvs/$r/"'
done
trap - INT
[ "$quit" -eq 1 ] && exit
# rest of script updates checked-out CVS repositories from local copy
アイデアは、ループの実行Ctrl+C中にループとそのプロセスをrsync
中断することなく、後でスクリプトの2番目の部分(ストアで更新された内容によっては常に実行したくない場合があります)をスキップするためにキーを押すことができるということです。su
rsync
これは機能せず、rsync
プロセスは信号を受信して終了します(そしてfor
ループの次の反復が続きます)。 rsync
次のように言います(Ctrl+Cスクリプトが終了するまで数回押したとき)。
^Crsync error: received SIGINT, SIGTERM, or SIGHUP (code 20) at rsync.c(642) [generator=3.1.3]
rsync error: received SIGINT, SIGTERM, or SIGHUP (code 20) at io.c(504) [receiver=3.1.3]
Wait...
rsync: [receiver] write error: Broken pipe (32)
rsync error: received SIGINT, SIGTERM, or SIGHUP (code 20) at io.c(1633) [sender=3.1.3]
^Crsync error: received SIGINT, SIGTERM, or SIGHUP (code 20) at rsync.c(642) [generator=3.1.3]rsync error: received SIGINT, SIGTERM, or SIGHUP (code 20) at io.c(504) [receiver=3.1.3
]
rsync: [receiver] write error: Broken pipe (32)
Wait...
^Crsync error: received SIGINT, SIGTERM, or SIGHUP (code 20) at rsync.c(642) [generator=3.1.3]
rsync error: received SIGUSR1 (code 19) at main.c(1440) [receiver=3.1.3]
Wait...
「という質問に対する回答によると、ctrl+c /not/ while ループを中断するには?「少なくとも実行中は、bash
次のことができるはずです。無視するsignal INT
、これは子プロセスもシグナルを無視します。理想的ではありませんが、試してみることができて嬉しいです。
したがって、2番目の試みは次のようになります。
#!/usr/local/bin/bash
trap '' INT
for r in CVSROOT src xenocara ports; do
su cvsuser -c 'rsync --archive --itemize-changes --delete --omit-dir-times \
"rsync://anoncvs.eu.openbsd.org/OpenBSD-cvs/$r/" \
"/extra/cvs/$r/"'
done
trap - INT
read -p 'Press enter or interrupt...' junk
# rest of script updates checked-out CVS repositories from local copy
これによりrsync
プロセスが中断される可能性がありますCtrl+C。
まあ、おそらくsu
信号マスクをリセットする理由ですか? 3回目の試み:
#!/usr/local/bin/bash
trap '' INT
for r in CVSROOT src xenocara ports; do
su -s /usr/local/bin/bash cvsuser -c \
'trap "" INT; rsync --archive --itemize-changes --delete --omit-dir-times \
"rsync://anoncvs.eu.openbsd.org/OpenBSD-cvs/$r/" \
"/extra/cvs/$r/"'
done
trap - INT
read -p 'Press enter or interrupt...' junk
# rest of script updates checked-out CVS repositories from local copy
いいえ、喜びはありません。プロセスrsync
は次のとおりです。まだ同様に中断可能です。
私が(最初に)意図したとおりにスクリプトを機能させる方法はありますか?
bash
私のコンピュータのバージョンは4.4.23です。これはPOSIXモードで動作するOpenBSDの基本的なバリエーション/bin/sh
です。pdksh
ベストアンサー1
それでは、実際に割り込みをしたくないのですが、ターミナルレベルで割り込みをどのように無効にしますかstty intr ""
?これにより、入力バッファにプレーン文字として表示され、^C
そこから読み取ることができます。
これはLinuxで私にとって効果的です。
#!/bin/bash
t=$(stty -g)
stty intr ""
echo please hold
sleep 5
stty "$t"
# short timeout, just check if there was any input earlier
read -n1 -t0.1 a
[[ "$a" = $'\003' ]] && echo "you hit ^C"
(OpenBSDではテストできませんでしたが、端末設定は標準であると仮定します。)