既出じゃないことを祈る.
リハビリ更新です.
TL;DR
- リモートのLinuxサーバーで作業終わったら,Windowsでアラームしたい.
- どうも Powershellの
New-BurntToastNotification
というものをつかえばいいらしい. - WSLからPowershell叩けばいいよね.
必要なもの
- Windows(検証: Windows 11 21H2 220000.652)
- Powershell version 5(以上?)(検証: 5.1.22000.652)
- WSL(検証: Ubuntu 20.04.4 LTS/WSL2 Kernel 5.10.102.1)
- ssh, netcat, sh
- Linux鯖(検証: Ubuntu 18.04 LTS)
- sshd, netcat, sh
New-BurntToastNotificationとやらについて
TL;DR
# Policy変えて
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
# インスコ
Install-Module -Name BurntToast
# 一応(?)いんぽーと
Import-Module BurntToast
# 実行テスト
New-BurntToastNotification -Text hoge
# -Sound Call[|2-10], -Sound Alarm[|2-10]で着信やアラーム音できる.
New-BurntToastNotification -Text piyo -Sound Alarm
# Logoアイコンもいける
New-BurntToastNotification -Text hoge -AppLogo C:\path\to\logo.png
WSLからテスト
powershell.exe "New-BurntToastNotification -Text fuga"
テスト
nc越し
$ powershell.exe "New-BurntToastNotification $(nc -w1 -lvp47123 -s"127.0.0.1" >& /dev/null)" &
$ lsof -i:47123 # check listening
$ echo "-Text fuga" | nc 192.0.2.1 47123 -w1 # failed(no localhost address)
$ echo "-Text hoge" | nc localhost 47123 # success
ssh越し
user@local:~$ powershell.exe "New-BurntToastNotification $(nc -w1 -lvp47123 -s"127.0.0.1" >& /dev/null)" &
user@local:~$ ssh -R 47123:127.0.0.1:47123 remote
user@remote:~$ echo "-Text hoge" | nc localhost 47123
シェルスクリプト書く.
source below_shellscript.sh
# 47123ポートでやりとり
export WSL_NOTIF_PORT="47123"
# WSLだったら....
if [[ -v WSL_DISTRO_NAME ]];then
# WSL通知待ちを定義
_waitWslNotification() {
WSL_NOTIF_LOGO_PATH=" "
# lsb-release呼んで Ubuntuなら,WSLのdotfilesの中に突っ込んであるubuntu.pngを抜く.
# ほかの奴はTux君(linux.png)表示.
source /etc/lsb-release
case "$DISTRIB_ID" in
"Ubuntu") logo="-AppLogo $(wslpath -w "$HOME/.zsh/assets/logos/ubuntu.png")" ;;
*) logo="-AppLogo $(wslpath -w "$HOME/.zsh/assets/logos/linux.png")" ;;
esac
#
while true; do
recv="$(nc -w1 -lvp"$WSL_NOTIF_PORT" -s"127.0.0.1")"
# 受信データあれば通知!
[[ "$recv" != "" ]] && powershell.exe "New-BurntToastNotification $logo $recv"
done
}
# 47123ポート使ってなかったら,実行する.
if ! (lsof -i:"$WSL_NOTIF_PORT" > /dev/null 2>&1);then
# &!で裏で実行かつシェル閉じても実行し続けるようにしとく(デーモンでよくないか?)
_waitWslNotification &! >&/dev/null
fi
fi
# nc投げるだけのWrapper関数
## help text
_wslnotify_help(){
cat << USAGE
Usage: wslnotify [-a AlarmNumber(1-10) | -c CallNumber(1-10)] [-t text]
Options:
-a | --alarm [number]: ring alarm
-c | --call [number]: ring alarm
-t | --text [text]: notify text
-v | --verbose: verbose mode
-h | --help: help text(this)
USAGE
}
## main
wslnotify() {
text=""
sound=""
verbose=1
# check args
OPTS=$(getopt -o hva:c:t: -l help,verbose,alarm:,call:,text: -- "$@")
p=$?
if ! $(return $p) || [[ $# -eq 0 ]]; then
_wslnotify_help
return 1
fi
# rotate args
eval set -- "$OPTS"
while true; do
case $1 in
-h | --help)
_wslnotify_help
return 0
;;
-v | --verbose)
verbose=0
shift
;;
-a | --alarm)
if [[ $2 -lt 1 ]] || [[ $2 -gt 10 ]];then
echo "Error: Invalid Alarm Number: $2"
return 1
fi
if [[ $2 -lt 1 ]] || [[ $2 -gt 10 ]];then
echo "Error: Invalid Call Number: $2"
return 1
fi
sound="-Sound Alarm$2"
[[ $2 -eq 1 ]] && sound="-Sound Alarm"
shift 2
;;
-c | --call)
sound="-Sound Call$2"
[[ $2 -eq 1 ]] && sound="-Sound Call"
shift 2
;;
-t | --text)
text="-Text $2"
shift 2
;;
--)
shift
break
;;
*)
echo "Error: getopts error." >&2
return 1
;;
esac
done
# verbose mode
if $(return $verbose);then
echo "VERBOSE: Send to \"$sound $text\""
fi
# sending
echo "$sound $text" | nc -w1 127.0.0.1 "$WSL_NOTIF_PORT"
}
# sshするときにプロキシ張る
alias ssh='ssh -R ${WSL_NOTIF_PORT}:localhost:${WSL_NOTIF_PORT}'
TODO:
- Socket用意してる状態で何回も
ssh -R 47123:localhost::47123
していいのか?- Socketファイルの有る無しで挙動変えさせる?
alias ssh
-->function ssh()
- Socketファイルの有る無しで挙動変えさせる?
-
nc
に依存せずに,/dev/tcp/localhost/47123
だっけ?,を使えないか? - 47123を開けっ放しにできないか?(
-k
使えたっけ) -
wslnotify
じゃなくてwinotify
のほうがいいかも
End of Article
- WSLを用いたSSH接続状態におけるクライアントWindows通知の実装した.
-
tmux
上で長い処理をしてたけど,いつ終わるのかをSlackとかにWebhookで送ってたけど,よりシンプルに通知できた. - 今後はSlack webhookで用いてたプロセス監視スクリプトと合体し,処理が終わったら自動的に通知するようにしたりを検討する.
- また,
tmux
の子プロセスでフォアグラウンドで動くプロセスで,一定時間以上走っているものがQUITしたら自動的に通知とか,ひまがあればやってみる.