Soak in Script

05/21

Script per se Script

世の中はスクリプトでできている。

almost everything consists of script.

Windows、macOS、Linuxとスクリプトが動く環境は数多くある。
最近WindowsもUbuntu Bashをエミュレートできるようなので
Shell Scriptの環境が各プラットフォームで整ってきている。
世の中を手軽に便利にできるスクリプト言語。
ちょっと思いついたアイデアをスクリプトで実現できるか調べてみるコーナー。
出来る限り、コマンド一発で解決したいなと。

基本的にここではUbuntu Bashで動作を確認している。


ファイル内の特定のブロックを除外(未完)

このサイトはMarkdownファイルを記事として変換してアップしている。
さらに記事をしゃべらせるために、音声合成プログラムにそのMarkdownファイルを渡しているのだが、ファイルの中にはしゃべらせなくてもよい部分がブロック単位で存在していたりする。
なので、その部分を省いて音声合成プログラムへ渡したい。
そこで、Markdownファイルの特定のブロック(存在する数、行数は不定)を取り除いた状態で次の工程に渡すためにはどうしたらよいか。
markdownファイルでblockquoteやcodeタグを使った引用ブロックはコードを貼り付けていたりするので、読み上げる必要がない。
そこは省きたいという話。
ブロックの始まりは「`````````html」「`````````mermaid」「{%」などから始まる。
そして終わりは「%}」や「`````````」と決まっている。
引用する行は1行~N行なんで、単純にgrepするには不便。
もうBashにさせなくてもよい気がしてくる問題。

さて、やってみる。

$ export FILENAME=./source/test.md && \
    cp $FILENAME /tmp/dump.txt && \
    for n in {1..10};
    do 
        cat -n /tmp/dump.txt |\
        grep -E '({%|```[^$]+$)' |\
        sed -e 's/^[^0-9]*\([0-9]\)/\1/' |\
        awk '{print $1;}' |\
        head -1 |\
        while read b;
        do 
            cat -n /tmp/dump.txt |\
            sed -e 's/^[^0-9]*\([0-9]\)/\1/' |\
            grep -A 1000 "^${b}" |\
            grep -E '(%}|```[ \t]*$)' |\
            awk '{print $1}' |\
            head -1 |\
            xargs -Iend echo "sed -e ${b},endd -i /tmp/dump.txt" |bash;
        done;
    done && mv /tmp/dump.txt ${FILENAME/%.*}_result.${FILENAME##*.}

同じファイルを何度もcatしたりcpとmvをしている。
もうワンライナーと呼べるのかはなはだ疑問。
仕組みとしては

sed -ie SSS,EEEd file

これを使って該当ブロックを削除してしまおうという仕組み。
今のところ、要件を満たしていないところが

  • 削除ブロック数が10個までしか対応していない
  • 行内にそのブロックがあった場合その行ごと削除する

こんな感じ。

2段階検索-別解2

さらに前回とは別のやり方を考えてみた。

条件は一緒。

$ cat /var/log/app.log
・
・
・
$ !! |grep "$(!! |grep failed |sed -e 's/^.*\[\([0-9]\{1,5\}.[0-9]\{1,5\}\)\].*$/\1/')"  |\
awk '{print $1,$2,$3,substr($0, index($0, ": "));}'
Dec 1 07:43:02 : connect start
Dec 1 07:43:05 : command execute
Dec 1 07:43:11 : command failed
$ 

一度Historyに残したら、わざわざ同じファイル名を二度打ちしなくてよいかなと。
ワンライナーではなくなるけど。

俺今何歳?

って、20代後半頃から思うようになってきた。
なのでスクリプトですぐわかるようにしたい。

$ echo -n "tell me your birthday?[eg.19000101] " && \⏎
read bday && \⏎
echo -n $bday | \⏎
sed -e 's/\([0-9]\{4\}\)\([0-9]\{2\}\)\([0-9]\{2\}\)/\1\/\2\/\3 00:00:00.000/' | \⏎
xargs -I@ date +%s -d @ | \⏎
xargs -I@ expr $(date +%s) - @ | \ ⏎
xargs -I@ expr @ / 60 / 60 / 24 / 365⏎
tell me your birthday?[eg.19000101] 19940930 ⏎
25
$ 

もっと簡単な方法がありそうだ。
最近思うのが、``でコマンドを実行する記述よりも
$( )で記述する方が見やすいのではと。


歌詞検索

いつも思うが、誰がこんなの使うんだと。
例えば、誰もいないマシン室。
サーバで独りモクモクと作業中に
ふと口ずさむ歌のフレーズ。

たっとえびゃ~ きぃみぃがいるだぁけーでっ

排熱用ファンと風の音の中
下手くそな自分の声がかき消される。
そこでふと疑問に思う。
あれ?これ誰の曲だっけ?
スマホなんてマシン室に持ってきてるわけないし
ネットに繋がるのこのサーバしかない。

なんてときに便利。(おい

では、やってみる。

$ echo -n "Type lyrics you search? " && \
read i && \
echo -n ${i} | \
sed -e 's/ /+/g' |\
xargs -ILYRIC curl -s "https://歌詞検索サイト/search/?Aselect=4&Bselect=3&x=0&y=0&Keyword=LYRIC" |\
grep "side td1" |\
sed -e 's/^[^<]*</</; s/<a[^>]*><img[^>]*><\/a>//; s/^<[^>]*><[^>]*><[^>]*>//; s/<[^>]*><[^>]*><[^>]*><[^>]*>\([^<]*\)<.*/ \- \1/'
Type lyrics you search? たっとえびゃ~きぃみぃがいるだぁけーでっ
きぃみぃがいるだぁけーでっ - オレオレワールド

こんな感じ。
歌詞と検索結果は諸事情で適当にいれている。

まぁこういうWebScraping系はナマモノなので
今はうまくいくけど、明日にはどうなっているか
わからないのが注意。


WOLパケット(マジックパケット)送信

Wakeup On LAN対応のPCをリモートで起動させたい。

例えば、待機任務中に原付きバイクをノーヘルで二人乗りで
無断外出をして飲酒運転で帰ってきたことで謹慎処分を
受けている地方公務員とその仲間が下宿先でシミュレーション
プログラムを作っているとする。(は?)

実行に使っているPCではとても短時間で処理仕切れないと
わかったときに、

ここの余裕じゃおっつかねーや

と言って、会社の電算室のコンピュータのリソースを
使うために、リモートから起動するときに使う。(は?)1

さて、どうするか。
Wakeup-On-LANの仕組みを調べたところ
どうやら起動対象のPCのMACアドレスを含めた
UDPパケットをブロードキャストで流せばOKらしい。
ポート番号はよくわからないけど対象にパケットが
届けば特に問題なさそうな予感。ここでは2304とする。

データグラムの仕様は
まず6バイト分を0xffで埋めて、その後にMACアドレスを
16回続けて書くようだ。

MACアドレスは区切り文字を含めない12文字の16進数表記と
なっているのでバイトに換算しなおすと6バイトを
16回続けるので

6 + 6 * 16 = 102

トータル102バイトになる。
このデータグラムをどうやって作って
投げるか。さてどうするか。

echo -eで実現できそうだ。
こんな感じ。

$ export MAC="HH:HH:HH:HH:HH:HH" &&\⏎
echo -ne "$(for i in `seq 1 6`;do echo -n "\xff" ;done)$(for i in `seq 1 16`;do echo $MAC |sed -e 's/:/\n/g' |while read j;do echo -n "\x${j}"; done; done)" |\⏎
nc -u 255.255.255.255 2304⏎

いかがだろうか。
実はWOL対応のPCが手元にないので確認できない、、、。
ncコマンドに渡す前に、od -xとかして確認したときには
問題なさそうなのは見たのだが、、、。

2018/04/25追記

そういえば、遠隔地の機械にWOLパケット送ることできるんだったっけ?
そういやブロードキャストってセグメント越えられないじゃん。


mailコマンドでの一括既読

今時Linuxの中で生活している人なんていないとは
思うが、たまにターミナルを覗くとよくわからん
メールが大量にSpoolに残っているときがないだろうか。
mailコマンドで見ると、、、

$ mail⏎
"/var/mail/hogehoge": 680 messages 680 unread
>U   1 Cron Daemon        金  9月 29 22:  **/***   Cron <root@localhost> /root/bin/test.sh 
 U   2 Cron Daemon        金  9月 29 22:  **/***   Cron <root@localhost> /root/bin/test.sh
 U   3 Cron Daemon        金  9月 29 23:  **/***   Cron <root@localhost> /root/bin/test.sh
 U   4 Cron Daemon        金  9月 29 23:  **/***   Cron <root@localhost> /root/bin/test.sh
 U   5 Cron Daemon        土  9月 30 00:  **/***   Cron <root@localhost> /root/bin/test.sh
 U   6 Cron Daemon        土  9月 30 00:  **/***   Cron <root@localhost> /root/bin/test.sh
 U   7 Cron Daemon        土  9月 30 01:  **/***   Cron <root@localhost> /root/bin/test.sh
 U   8 Cron Daemon        土  9月 30 01:  **/***   Cron <root@localhost> /root/bin/test.sh
 U   9 Cron Daemon        土  9月 30 02:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  10 Cron Daemon        土  9月 30 02:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  11 Cron Daemon        土  9月 30 03:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  12 Cron Daemon        土  9月 30 04:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  13 Cron Daemon        土  9月 30 04:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  14 Cron Daemon        土  9月 30 05:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  15 Cron Daemon        土  9月 30 05:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  16 Cron Daemon        土  9月 30 05:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  17 Cron Daemon        土  9月 30 05:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  18 Cron Daemon        土  9月 30 06:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  19 Cron Daemon        土  9月 30 06:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  20 Cron Daemon        土  9月 30 06:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  21 Cron Daemon        土  9月 30 06:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  22 Cron Daemon        土  9月 30 07:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  23 Cron Daemon        土  9月 30 07:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  24 Cron Daemon        土  9月 30 07:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  25 Cron Daemon        土  9月 30 08:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  26 Cron Daemon        土  9月 30 08:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  27 Cron Daemon        土  9月 30 08:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  28 Cron Daemon        土  9月 30 08:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  29 Cron Daemon        土  9月 30 08:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  30 Cron Daemon        土  9月 30 09:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  31 Cron Daemon        土  9月 30 09:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  32 Cron Daemon        土  9月 30 09:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  33 Cron Daemon        土  9月 30 09:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  34 Cron Daemon        土  9月 30 09:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  35 Cron Daemon        土  9月 30 09:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  36 Cron Daemon        土  9月 30 09:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  37 Cron Daemon        土  9月 30 10:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  38 Cron Daemon        土  9月 30 10:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  39 Cron Daemon        土  9月 30 10:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  40 Cron Daemon        土  9月 30 10:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  41 Cron Daemon        土  9月 30 10:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  42 Cron Daemon        土  9月 30 10:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  43 Cron Daemon        土  9月 30 10:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  44 Cron Daemon        土  9月 30 10:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  45 Cron Daemon        土  9月 30 11:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  46 Cron Daemon        土  9月 30 11:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  47 Cron Daemon        土  9月 30 11:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  48 Cron Daemon        土  9月 30 11:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  49 Cron Daemon        土  9月 30 11:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  50 Cron Daemon        土  9月 30 11:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  51 Cron Daemon        土  9月 30 11:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  52 Cron Daemon        土  9月 30 12:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  53 Cron Daemon        土  9月 30 12:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  54 Cron Daemon        土  9月 30 12:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  55 Cron Daemon        土  9月 30 12:  **/***   Cron <root@localhost> /root/bin/test.sh
 U  56 Cron Daemon        土  9月 30 12:  **/***   Cron <root@localhost> /root/bin/test.sh
?

と、私の作ったしょうもないスクリプトを実直にもCronさまが
実行なさってらっしゃった結果がこんな状況を生み出した。
さてこれを全部みるなんてことは現実的に不可能というか
みてらんないけど、中にはもしかして有用(削除しちゃ駄目)な
ものがあるかもしれない。なので、/home/hogehoge/mboxに
とりあえず退避しておきたい。
てっとり早いのは

$ cat /var/mail/`whoami` >>$HOME/mbox && echo >/var/mail/`whoami`⏎

みたいな感じなんだろうけど、これが良い方法なのかよくわからない。
なので、以下のようにしてみた。

$ for i in `seq 1 680`; do mail <<<1 >/dev/null; done⏎

680通のメールを1通ずつ読んだことにすれば
自動的にmboxに保存されていくはずなので
680回メールの一覧の1通目を読むようにした。
mailコマンドはターミナルの画面サイズによって
一覧表示できるメールの数が決まっているため
ループで使っている$iはそのままコマンドに
渡せない。ま、大したことないコマンドだな。


カラーテーブル逆引き

どこにこんな需要があるのか知らないけどこんなのはどうだろう。
CSSとかでよく使うカラーコードを入れると色の名前を返してくれるってやつ。

なんだろう、使うのかな?
一応書いてみるか。今回はWEB色見本のサイトcolordic.orgさんの
サイトを参考にしている。

$ echo -n "Enter color code you search? " && \ ⏎
read i && \ ⏎
curl -s https://www.colordic.org/colorsample/ |\ ⏎
grep "<a style=\"" | grep "${i}" | \ ⏎
sed -e 's/^.*<a style=\"border\-color:\([^\"]*\)\"[^$]*>\([^<]*\)<\/a>$/The answer is \2 (\1)/g' |\ ⏎
grep -v "is #" ⏎

Enter color code you search? 000000
The answer is black (#000000)
The answer is ブラック (#000000)

$ 

いかがだろうか。
今回はインタラクティブなコマンドにしてみた。
こいつの便利なところはカラーコードを全部入れなくても
曖昧検索できるところ。

$ echo -n "Enter color code you search? " && \  ⏎
read i && \  ⏎
curl -s https://www.colordic.org/colorsample/ |\  ⏎
grep "<a style=\"" | grep "${i}" | \  ⏎
sed -e 's/^.*<a style=\"border\-color:\([^\"]*\)\"[^$]*>\([^<]*\)<\/a>$/The answer is \2 (\1)/g' |\  ⏎
grep -v "is #"  ⏎

Enter color code you search? a8
The answer is salmon (#fa8072)
The answer is 蘇芳香 (#a86965)
The answer is 遠州茶 (#ca8269)
The answer is 胡桃色 (#a86f4c)
The answer is 柳色 (#a8c97f)
The answer is 青白橡 (#9ba88d)
The answer is 山葵色 (#a8bf93)
The answer is 花浅葱 (#2a83a2)
The answer is 紺瑠璃 (#164a84)
The answer is 薄色 (#a89dac)
The answer is オーカー (#ba8b40)
The answer is エジプシャンブルー (#0073a8)
The answer is ブルーラベンダー (#a4a8d4)
The answer is オーキッドピンク (#da81b2)
$

もちろん、カラー名でも検索できる。
ただこれだと

ふぁ?結局色分からねーじゃん。

ってなると思うので色も分かるようにしたい。
最近はターミナルも24bitの色表現ができるのが
増えているのでこれを使わない手はない。
ってことで、色を入れたらその色を出すことに。

$ echo -n "Enter color code you search? " && \ ⏎
read i && \ ⏎
curl -s https://www.colordic.org/colorsample |\ ⏎
grep "<a[^>]*style=\"" |\ ⏎
sed -e 's/ href=\"[^$]*\">/>/' |\ ⏎
grep "${i}" | \ ⏎
sed -e 's/^.*<a[^>]*style=\"border\-color:\([^\"]*\)\"[^$]*>\([^<]*\)<\/a>$/\2 \1/g' |\ ⏎
grep -v "^#" |\ ⏎
while read j; ⏎
do ⏎
a=$j; echo -n ${j##*#} |\ ⏎
sed -e 's/\(..\)\(..\)\(..\)/0x\1 0x\2 0x\3/' |\ ⏎
awk '{system("echo -n $(("$1")) $(("$2")) $(("$3"))");}' |\ ⏎
xargs -IARGS echo -n ARGS $a |\ ⏎
awk '{system("printf \047\x1b[48;2;%s;%s;%sm\047 "$1" "$2" "$3"; echo -n \"The answer is "$4" ("$5")\"; printf \047\x1b[0m\047; echo ;");}' ; ⏎
done ⏎

execution result

いかがだろうか。
ポイントはCSSで#ffffffとか書いているのを
ターミナルにどうやって\x1b[48;2;RR;GG;BBmって形式で
渡すかってところ。

そしてここまでやってふと頭によぎる最大の命題。

これって誰が必要なの??

う、、うん、、、まぁ、私? ぐらい?? みたいな???

てきな?????

は?


2段階検索

さて2段階検索ってことをしてみたい。
例えば、あるログファイル/var/log/user.logがあるとする。
中身は以下の通り。

Dec 1 07:43:01 excalibur appA[25033.25037]: connect start
Dec 1 07:43:02 excalibur appA[25033.25038]: connect start
Dec 1 07:43:04 excalibur appA[25033.25037]: command execute
Dec 1 07:43:05 excalibur appA[25033.25038]: command execute
Dec 1 07:43:09 excalibur appA[25033.25039]: connect start
Dec 1 07:43:10 excalibur appA[25033.25037]: command successful
Dec 1 07:43:10 excalibur appA[25033.25040]: connect start
Dec 1 07:43:10 excalibur appA[25033.25040]: command execute
Dec 1 07:43:11 excalibur appA[25033.25038]: command failed
Dec 1 07:43:11 excalibur appA[25033.25039]: command execute
Dec 1 07:43:15 excalibur appA[25033.25039]: command successful
・
・
・

これはexcaliburというホスト名のサーバがappAという
サービスを常駐させていて、appAは不定期のタイミングで
あるコマンドを実行する。
コマンドを実行するときは必ず別スレッドを立ち上げるため
ログには同じプロセス名でスレッドIDだけが違うログが
__ 接続→コマンド実行→実行(完了|失敗) __
というサイクルで書き込まれている。

さて今回のお題目は、上記ログにfailedを出力してコマンドが
失敗しているログがあるのだが、その接続開始時刻とコマンド
失敗時刻を知りたい。さぁどうする?
失敗時刻はfailedをgrepすればよいのだが、問題はfailedを
吐いたスレッドが実行された時刻をどうやって知るか。
上記例だと1回しかでてないが失敗は何度も出ることを想定する。
んで、いつもの通りコマンド一発で出したい。

ではやってみる。

$ tail -f /var/log/app.log |\
grep failed |\
sed -e 's/^.*\[\([0-9]\{1,5\}.[0-9]\{1,5\}\)\].*$/\1/' |\
xargs -ITHRDID grep "THRDID" /var/log/app.log |\
grep -E "(connect start|command failed)"    |\
    awk '{print $1,$2,$3,substr($0, index($0, ": "));}' 
Dec 1 07:43:02 : connect start
Dec 1 07:43:11 : command failed

どうだろうか。ま、今回も「こんな長いコマンド打てっか!?」
ってレベルの長いワンライナーになってしまったな。
ちなみにこれCtrl + Cでないと抜けられないので注意。


円ドル換算

これも需要があるかはわからん。
例えば、、、
ターミナルで作業してて、このサーバ遅せーなぁ。
そろそろサーバ買い換えるかなと思い立って徐ろに

$ w3m -F http://google.com/

って打って海外サイトとかで市場調査とか
始めちゃったりする。すると、中古のブレードサーバが
$299とか書いてたりして速攻で円で計算したくなる。
みたいな人用のコマンド。(は?

では早速コマンド一発でやってみる。
今回換算にはCurrencyConverterRate.comさんのページを参考に
している。
また今回実数の乗算にbcコマンドを使っている。

$ export myCUR=299 && \
curl -s -q http://jp.currencyconverterrate.com/usd/jpy.html |\
grep -A 1 -E "<td>1 (JPY|USD) = <\/td>" |\
head -2 | tail -1 |\
sed -e "s/<[^>]*>//g; s/JPY//; s/USD//; s/ //g" |\
xargs -ICUR echo "scale=5; CUR * ${myCUR}" |\
bc | sed -e "s/^\./0./"
33279.298

こんな長いコマンド打ってられっか!
ってなるよね。ちょっと塩梅悪いな。

ただシェルスクリプトにしたら比較的便利に使える。
URLのusdとjpyってパスのところを交換するだけで
USドル⇔日本円の相互変換ができるから。


文章を画像に変換

こんなん誰に需要があるんだって感じだけど
例えば、普段パソコン起動しないと見れないような情報を
スクリプトでかき集めてまとめて画像ファイルにしておいて
dlnaサーバに保存しておく。

で、スマホやPS3、ブラビアのようなdlnaクライアントからその画像を見ると、
パソコン起動しなくても見れるって寸法。ま、ニッチだよね。

では、パソコンを起動しないと見れない情報ってなんだ?っていうと
例えばサーバのログとか、ブログのアクセス数とかなんとか。

それでは、ここでは例として家のファイルサーバのディスク容量を
画像ファイルにしてみることにする。
ここで必要なのはdfコマンドとImageMagickパッケージ内のconvertコマンド
日本語フォント。dfコマンド結果によっては日本語フォントでなくてもよい
けど、ま、無難に日本語フォントにしておけばよい。私は日本語TrueTypeフォント
にしてみた。

$ df -h |\
convert -background white -fill black -font /usr/share/fonts/truetype/fonts-japanese-gothic.ttf -pointsize 32 label:@- /tmp/df-result.png

こんなんでどうだろう?
白地に黒い字でdf結果が画像になっているはず。


ファイル名の一括変換

規則性のない名前のついたファイルが数百とあるディレクトリの中から
ある一定のファイルたちの名前を規則性のあるファイル名に変更したい。
例えば、更新日付が3日以上前のファイルを

deleteable_日付_連番_元のファイル名.拡張子

というファイル名にしたいとする。
さてどうやるか。

3日以上経ったかはfindのオプションで抽出するとして
問題は連番をどう管理するか。
seqコマンドでseq 1 100なんて使ったら、
同日に2回実行されたら同番ができちゃうし。

そこで私は以下のようにしてみた。

$ find ./対象のディレクトリ/ -mtime +3 -type f -print |\
while read i;
do
mv ${i} deleteable_$(date +%Y%m%d)_$(ls -l |grep deleteable_$(date +%Y%m%d)_ |wc -l |xargs -Innn expr nnn + 1)_$(basename ${i});
done

どうだろうか。おそらく数百のファイルならストレスなくいけるけど
数十万ファイル単位だと多分遅くて使い物にならないかも。


○○○○占いの傾向を探る

いつも朝に見ている○○○○テレビ
で毎回やっている
○○○○占い

それで私の星座がいつも悪いような気がしてならない。
そこで、毎日結果を保存しておけば、後で傾向が分かるので
どうやらWebから情報が見れるみたいなので
毎日12:00に占い結果を蓄積しておくことに。

保存する情報は、日付と12個の順位。
ページを見る限り1位から順番に上から表示されているので
おそらく何も考えずに上から並べれば、自ずと順番に並ぶ寸法だと。
さてスクリプトはというとこんな感じ。

$ curl -s http://****占いのURL/ |\
grep -E "(<span>[^<]*<\/span>)" |\
sed -e 's/<[^>]*>//g; /^ .*/d' |\
while read i;
do
echo -n "${i}," |\
tr -d \\r >> fortunedb.csv;
done && echo "" >>fortunedb.csv

ファイル名が2回出てきているのが駄目だな。
毎日12:00に実行はスケジューラにおまかせ
Linuxの定番cronに任せちゃう。
以下のレシピをcrontabに追加したらよい。

0 12 * * 1,2,3,4,5 上記コマンド

めざまし占い(言っちゃった)は月曜から金曜までなので
土日は動かないようにすると。


ネットワーク帯域を調べる

Linuxでネットワーク帯域を調べたいなと。
そう思ったきっかけはインターネットがとても
遅くなるときがあったから。
現在契約しているフレッツ光が悪いのか
はたまたLAN環境に何かあるのか、別の要因も考えられる。
ただ何時遅くなるのかが皆目検討もつかない。

そこで、帯域を定期的に調べて、著しく遅い時間帯を
調べてみることに。

と、前置きはここまでにして
bashスクリプトで帯域をどうやって調べようかなと。
まずは材料を集めてみることに。

普通に思いつくのは疎通確認にいつも使っているping。
コマンドの実行結果にrttの平均が出力される。
rttはこっちからデータを送ってその返事(ACK)が
返ってくるまでの時間のこと。つまりあるデータ量を
目的のところまで送信するまでにかかった時間
=スループットとして導き出せると。

例えば、インターネットで使用されているTCPの
ウインドウサイズは65535Bを最大としている。
したがって、このウインドウサイズと同じデータサイズを
送ってその返答時間を測ればネットの帯域が分かると。
さらにpingは送ったデータをそのまま返すので
通信量は倍ということに。

さてここでいささか問題が。
bashスクリプトだと小数点以下を扱うのに面倒くさい。
exprコマンドは基本整数しか使えないし。
そこでawkコマンドを使ってみる。
ではやってみよう。

$ ping -c 5 -s 65000 www.yahoo.co.jp |\
grep avg |\
awk 'BEGIN{FS="/";a=65000*2*8} {print (a/($5/1000))/100000;}'
43.4508654
$ 

こんな感じ。単位はMbps。
データサイズが2回登場しているので
ここはダサいかな。