遅延終了スクリプト

遅延終了スクリプト

/bin/sh私は最初にいくつかのCVSリポジトリのローカルコピーをに更新し、次に私のコンピュータからチェックrsyncアウトされたバージョンを更新するこのようなスクリプト(OpenBSDに書かれています)を持っています。このスクリプトは OpenBSD 経由で root として実行されます。doassudoOpenBSDの「同等」):

#!/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番目の部分(ストアで更新された内容によっては常に実行したくない場合があります)をスキップするためにキーを押すことができるということです。sursync

これは機能せず、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ではテストできませんでしたが、端末設定は標準であると仮定します。)

おすすめ記事