Quantcast
Viewing all 743 articles
Browse latest View live

某所で話題になってた『内閣府の「国民の祝日」CSV』をシェル芸で加工して見やすくする

なんか、某所で見にくい・加工しにくいと話題になってた『内閣府の「国民の祝日」CSV』について、シェル芸を使って加工して少し見やすくしたので備忘として残しておく(使うことはないだろうけど)。
このデータ、確かにそのままだと扱いにくいけど加工自体はそこまで難易度の高いものではないみたい。コンソール上で見やすくするため、CSVではなくTSVにして出力してみる(CSVにしたきゃ、awkのとこにある「\t」を「,」に変えればいいだけだし)。

以下、Linuxで実行できるコマンド。
文字コード・改行コードの変換にnkfコマンドが必要になるので、環境にインストールしておくこと。

curl -s http://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv | nkf -Luw | sed '1,3d;$d;s/,/ /g' | xargs -n2 | sort -Vk2 | awk '{print $2"\t"$1}'

Image may be NSFW.
Clik here to view.

blacknon@BS-PUB-DEVELOP:~$ curl -s http://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv | nkf -Luw | sed '1,3d;$d;s/,/ /g' | xargs -n2 | sort -Vk2 | awk '{print $2"\t"$1}'
2016/1/11       成人の日
2016/2/11       建国記念の日
2016/3/20       春分の日
2016/4/29       昭和の日
2016/5/3        憲法記念日
2016/5/4        みどりの日
2016/5/5        こどもの日
2016/7/18       海の日
2016/8/11       山の日
2016/9/19       敬老の日
2016/9/22       秋分の日
2016/10/10      体育の日
2016/11/3       文化の日
2016/11/23      勤労感謝の日
2016/12/23      天皇誕生日
2017/1/9        成人の日
2017/2/11       建国記念の日
2017/3/20       春分の日
2017/4/29       昭和の日
2017/5/3        憲法記念日
2017/5/4        みどりの日
2017/5/5        こどもの日
2017/7/17       海の日
2017/8/11       山の日
2017/9/18       敬老の日
2017/9/23       秋分の日
2017/10/9       体育の日
2017/11/3       文化の日
2017/11/23      勤労感謝の日
2017/12/23      天皇誕生日
2018/1/8        成人の日
2018/2/11       建国記念の日
2018/3/21       春分の日
2018/4/29       昭和の日
2018/5/3        憲法記念日
2018/5/4        みどりの日
2018/5/5        こどもの日
2018/7/16       海の日
2018/8/11       山の日
2018/9/17       敬老の日
2018/9/23       秋分の日
2018/10/8       体育の日
2018/11/3       文化の日
2018/11/23      勤労感謝の日
2018/12/23      天皇誕生日

せっかくなので、日付に曜日もつけてみる。

curl -s http://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv | nkf -Luw | sed '1,3d;$d;s/,/ /g' | xargs -n2 | sort -Vk2 | awk '{c="date -d \""$2"\" +%a";c|getline t;print $2"("t")\t"$1}'

Image may be NSFW.
Clik here to view.

blacknon@BS-PUB-DEVELOP:~$ curl -s http://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv | nkf -Luw | sed '1,3d;$d;s/,/ /g' | xargs -n2 | sort -Vk2 | awk '{c="date -d \""$2"\" +%a";c|getline t;print $2"("t")\t"$1}'
2016/1/11(月)   成人の日
2016/2/11(木)   建国記念の日
2016/3/20(日)   春分の日
2016/4/29(金)   昭和の日
2016/5/3(火)    憲法記念日
2016/5/4(水)    みどりの日
2016/5/5(木)    こどもの日
2016/7/18(月)   海の日
2016/8/11(木)   山の日
2016/9/19(月)   敬老の日
2016/9/22(木)   秋分の日
2016/10/10(月)  体育の日
2016/11/3(木)   文化の日
2016/11/23(水)  勤労感謝の日
2016/12/23(金)  天皇誕生日
2017/1/9(月)    成人の日
2017/2/11(土)   建国記念の日
2017/3/20(月)   春分の日
2017/4/29(土)   昭和の日
2017/5/3(水)    憲法記念日
2017/5/4(木)    みどりの日
2017/5/5(金)    こどもの日
2017/7/17(月)   海の日
2017/8/11(金)   山の日
2017/9/18(月)   敬老の日
2017/9/23(土)   秋分の日
2017/10/9(月)   体育の日
2017/11/3(金)   文化の日
2017/11/23(木)  勤労感謝の日
2017/12/23(土)  天皇誕生日
2018/1/8(月)    成人の日
2018/2/11(日)   建国記念の日
2018/3/21(水)   春分の日
2018/4/29(日)   昭和の日
2018/5/3(木)    憲法記念日
2018/5/4(金)    みどりの日
2018/5/5(土)    こどもの日
2018/7/16(月)   海の日
2018/8/11(土)   山の日
2018/9/17(月)   敬老の日
2018/9/23(日)   秋分の日
2018/10/8(月)   体育の日
2018/11/3(土)   文化の日
2018/11/23(金)  勤労感謝の日
2018/12/23(日)  天皇誕生日

 

…なんか嫌な予感がする。
曜日を少し加工しやすいようにして、集計してみよう。

# 曜日をタブ区切りで2列目にする
curl -s http://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv | nkf -Luw | sed '1,3d;$d;s/,/ /g' | xargs -n2 | sort -Vk2 | awk '{c="date -d \""$2"\" +%a";c|getline t;print $2"\t"t"曜日\t"$1}'

# 更に曜日別集計(わかりやすいよう改行入れる)
curl -s http://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv \
| nkf -Luw | sed '1,3d;$d;s/,/ /g' | xargs -n2 | sort -Vk2 | awk '{c="date -d \""$2"\" +%a";c|getline t;print $2"\t"t"曜日\t"$1}' \
| awk -F'[/\t]' '{print $1" "$4}' | sort | uniq -c | grep -E -e '^.*[土,日]曜日' -e $

Image may be NSFW.
Clik here to view.

blacknon@BS-PUB-DEVELOP:~$ curl -s http://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv | nkf -Luw | sed '1,3d;$d;s/,/ /g' | xargs -n2 | sort -Vk2 | awk '{c="date -d \""$2"\" +%a";c|getline t;print $2"\t"t"曜日\t"$1}'
2016/1/11       月曜日  成人の日
2016/2/11       木曜日  建国記念の日
2016/3/20       日曜日  春分の日
2016/4/29       金曜日  昭和の日
2016/5/3        火曜日  憲法記念日
2016/5/4        水曜日  みどりの日
2016/5/5        木曜日  こどもの日
2016/7/18       月曜日  海の日
2016/8/11       木曜日  山の日
2016/9/19       月曜日  敬老の日
2016/9/22       木曜日  秋分の日
2016/10/10      月曜日  体育の日
2016/11/3       木曜日  文化の日
2016/11/23      水曜日  勤労感謝の日
2016/12/23      金曜日  天皇誕生日
2017/1/9        月曜日  成人の日
2017/2/11       土曜日  建国記念の日
2017/3/20       月曜日  春分の日
2017/4/29       土曜日  昭和の日
2017/5/3        水曜日  憲法記念日
2017/5/4        木曜日  みどりの日
2017/5/5        金曜日  こどもの日
2017/7/17       月曜日  海の日
2017/8/11       金曜日  山の日
2017/9/18       月曜日  敬老の日
2017/9/23       土曜日  秋分の日
2017/10/9       月曜日  体育の日
2017/11/3       金曜日  文化の日
2017/11/23      木曜日  勤労感謝の日
2017/12/23      土曜日  天皇誕生日
2018/1/8        月曜日  成人の日
2018/2/11       日曜日  建国記念の日
2018/3/21       水曜日  春分の日
2018/4/29       日曜日  昭和の日
2018/5/3        木曜日  憲法記念日
2018/5/4        金曜日  みどりの日
2018/5/5        土曜日  こどもの日
2018/7/16       月曜日  海の日
2018/8/11       土曜日  山の日
2018/9/17       月曜日  敬老の日
2018/9/23       日曜日  秋分の日
2018/10/8       月曜日  体育の日
2018/11/3       土曜日  文化の日
2018/11/23      金曜日  勤労感謝の日
2018/12/23      日曜日  天皇誕生日
blacknon@BS-PUB-DEVELOP:~$
blacknon@BS-PUB-DEVELOP:~$ # 更に曜日別集計(わかりやすいよう改行入れる)
blacknon@BS-PUB-DEVELOP:~$ curl -s http://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv \
> | nkf -Luw | sed '1,3d;$d;s/,/ /g' | xargs -n2 | sort -Vk2 | awk '{c="date -d \""$2"\" +%a";c|getline t;print $2"\t"t"曜日\t"$1}' \
> | awk -F'[/\t]' '{print $1" "$4}' | sort | uniq -c | grep -E -e '^.*[土,日]曜日' -e $
      1 2016 火曜日
      2 2016 金曜日
      4 2016 月曜日
      2 2016 水曜日
      1 2016 日曜日
      5 2016 木曜日
      3 2017 金曜日
      5 2017 月曜日
      1 2017 水曜日
      4 2017 土曜日
      2 2017 木曜日
      2 2018 金曜日
      4 2018 月曜日
      1 2018 水曜日
      3 2018 土曜日
      4 2018 日曜日
      1 2018 木曜日

 

…2016年、とても恵まれた奇跡の年だったのですね。
2017年の祝日が結構土曜日と被ってるのは知ってたけど、まさか来年もとは…。悲しい…。
日曜は振替になるからいいけど、土曜日も振替休日欲しいなぁ。

あと、大晦日って国民の祝日じゃないんだ。知らなかった。

 

で、今回はこの程度のデータ量や難易度、更にあんまり使わなそうなデータだったからいいけど、これと同じことをもっと重要、かつ大きなデータとかでやられるのはどうかなと思う。
これ、文字コードや改行コードから推測するとWindowsで作ったんじゃないかな(高い確率でExcelから生成されてる気がする)。正直、データとしてはよろしい…とは言えないので、次は改善して欲しいなぁと。

 

Image may be NSFW.
Clik here to view.
「国民の祝日」の由来がわかる小事典 (PHP新書)
「国民の祝日」の由来がわかる小事典 (PHP新書)

『.ssh/authorized_keys』をログインユーザが編集できないようにする(rootのみ編集可能な状態にする)

sshの鍵認証で、特定のカギのみをrootで許可してやり、一般ユーザに勝手に追加させないようにしたいなぁ…という話があり、やり方を考えてみた。
で、当初は『.ssh/authorized_keys』ファイルの所有者をrootに変えてやり、一般ユーザには読み込み権限だけを与えてしまえばいいかなと思ったのだが、どうもそれではうまくいかない。というのも、『.ssh/』ディレクトリの所有者はその一般ユーザになるので、『.ssh/authorized_keys』を削除して作り変えてしまえるためだ。

[test@BS-PUB-CENT7-01 ~]$ ls -al .ssh/
合計 4
drwx------. 2 test test  28  2月 23 00:15 .
drwx------. 3 test test  90  2月 23 00:15 ..
-rw-r--r--. 1 root root 405  2月 23 00:15 authorized_keys
[test@BS-PUB-CENT7-01 ~]$ echo test > .ssh/authorized_keys
-bash: .ssh/authorized_keys: 許可がありません
[test@BS-PUB-CENT7-01 ~]$ echo test >> .ssh/authorized_keys
-bash: .ssh/authorized_keys: 許可がありません
[test@BS-PUB-CENT7-01 ~]$ cp .ssh/authorized_keys{,.bk}
[test@BS-PUB-CENT7-01 ~]$ rm .ssh/authorized_keys
rm: 書き込み保護されたファイル 通常ファイル `.ssh/authorized_keys' を削除しますか?y
[test@BS-PUB-CENT7-01 ~]$ cp .ssh/authorized_keys{.bk,}
[test@BS-PUB-CENT7-01 ~]$ ls -la .ssh/
合計 8
drwx------. 2 test test  53  2月 23 00:16 .
drwx------. 3 test test  90  2月 23 00:15 ..
-rw-r--r--. 1 test test 405  2月 23 00:16 authorized_keys
-rw-r--r--. 1 test test 405  2月 23 00:16 authorized_keys.bk

だからと言って、『.ssh』フォルダの所有者を変更してしまっては鍵認証でのログインはできない。ディレクトリの所有者なので、スティッキービットを設定しても意味がない。
ではどうすればいいのか?とりあえず、たとえディレクトリの所有者であろうとも『.ssh/authorized_keys』の削除を行えなければ回避できるはずだ。

という訳で、ファイルの所有者をrootにした状態で、さらにchattrを使って拡張属性で削除不可(追記のみ可能)にしてやればいけるのではないかと考えた。
所有者がrootであれば、一般ユーザでchattrを使ってもフラグを変更できないため、何もできないはずだ。

というわけで、さっそくやってみた。

[root@BS-PUB-CENT7-01 ~]# ls -la /home/test/.ssh/authorized_keys
-rw-r--r--. 1 root root 405  2月 23 00:16 /home/test/.ssh/authorized_keys
[root@BS-PUB-CENT7-01 ~]#
[root@BS-PUB-CENT7-01 ~]# # chattr +a で追記のみ可能にする
[root@BS-PUB-CENT7-01 ~]# chattr +a /home/test/.ssh/authorized_keys
[root@BS-PUB-CENT7-01 ~]# lsattr /home/test/.ssh/authorized_keys
-----a---------- /home/test/.ssh/authorized_keys
[root@BS-PUB-CENT7-01 ~]#
[root@BS-PUB-CENT7-01 ~]# su - test
最終ログイン: 2017/02/23 (木) 00:23:34 JST日時 pts/1
[test@BS-PUB-CENT7-01 ~]$
[test@BS-PUB-CENT7-01 ~]$ ls -la .ssh/authorized_keys
-rw-r--r--. 1 root root 405  2月 23 00:16 .ssh/authorized_keys
[test@BS-PUB-CENT7-01 ~]$ ls -la .ssh
合計 4
drwx------. 2 test test  28  2月 23 00:22 .
drwx------. 3 test test  90  2月 23 00:15 ..
-rw-r--r--. 1 root root 405  2月 23 00:16 authorized_keys
[test@BS-PUB-CENT7-01 ~]$
[test@BS-PUB-CENT7-01 ~]$ # 追記のみ可能だが、書き込み権限がないので何もできない
[test@BS-PUB-CENT7-01 ~]$ echo aaa > .ssh/authorized_keys
-bash: .ssh/authorized_keys: 許可がありません
[test@BS-PUB-CENT7-01 ~]$ echo aaa >> .ssh/authorized_keys
-bash: .ssh/authorized_keys: 許可がありません
[test@BS-PUB-CENT7-01 ~]$
[test@BS-PUB-CENT7-01 ~]$ # 追記のみ可能なので、ファイルの削除もできない
[test@BS-PUB-CENT7-01 ~]$ rm -rf .ssh/authorized_keys
rm: `.ssh/authorized_keys' を削除できません: 許可されていない操作です

 

もちろん、ssh-copy-idなどでも鍵の追加が行えないようになった。

blacknon@BS-PUB-DEVELOP:~$ ssh-copy-id -i test test@BS-PUB-CENT7-01
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "test.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
sh: .ssh/authorized_keys: 許可がありません

 

注意点としては、拡張属性で定義してしまってるので、rootであっても追記しか行えない状態になったということだろうか。
編集を行う場合は、一度属性を解除してから編集する必要があるので注意。

 

Image may be NSFW.
Clik here to view.
OpenSSH[実践]入門 (Software Design plus)
OpenSSH[実践]入門 (Software Design plus)

dateコマンド(+Faketime)で今年のプレミアムフライデー(各月の最終金曜日)を求める

先日、2017年02月24日よりプレミアムフライデーなるモノが始まった。これは、毎月の最終金曜日は15時退社にして余暇を作ることで個人消費を増やし、景気促進を促すという経産省主導の消費喚起のプログラムなのだが、あいにくと導入している企業は0.1%前後とかで、今の時点だとプレミアムな企業にしか適用されてないようだ(プレミアムな企業だったら給料も高いので、消費喚起という意味ではまぁ間違ってない…のか?景気対策としての効果は疑問だけど、まぁ結果を見てからかなぁ…)。
で、じゃあ今年のプレミアムフライデーは何日なのかをコンソール上で出力させてってみよう。日付関係の処理を行うといえばdateコマンドなので、今回はこれらを利用する。

 

1.Faketimeを用いる場合

さて、dateコマンドといえば、「-d」オプションで”last friday”とか指定すれば前回の金曜日の日付を取得してくれるのだが、この指定方法は日付を直接指定してから行えない。つまり、現在時刻からみての前回の金曜日が出力されてしまう。

blacknon@BS-PUB-UBUNTU-01:~$ date -d 'last friday'
2017年  2月 24日 金曜日 00:00:00 JST
blacknon@BS-PUB-UBUNTU-01:~$
blacknon@BS-PUB-UBUNTU-01:~$ # 直接指定した日付が優先されてしまう
blacknon@BS-PUB-UBUNTU-01:~$ date -d '2017/02/01 last friday'
2017年  2月  1日 水曜日 00:00:00 JST

 

でも、この-dで前回の金曜日を取得したい…。そんなときは、結構前にも触れたことのあるlibfaketimeをインストールするとよいだろう。これを使うことで、dateコマンドが認識する時刻をfaketimeで指定した時刻にだますことが可能になる。faketimeは前に紹介した時から結構進化しており、以下のようにyumやaptでインストールが可能となっている。

yum --enablerepo epel install libfaketime
apt install faketime
brew install libfaketime

 

で、あとはdateコマンドの実行前にfaketimeで適当な日付を指定してやる。

faketime 2017-01-01 date -d 'last friday'
[root@BS-PUB-CENT7-01 ~]# faketime 2017-01-01 date -d 'last friday'
2016年 12月 30日 金曜日 00:00:00 JST

 

これを応用してやれば、以下のように記述することで各月の最終金曜日、プレミアムフライデーを出力させることができる。

printf 'faketime %s date -d "last fri"\n' {17{02..12},1801}01|sh
[root@BS-PUB-CENT7-01 ~]# # ブレース展開はネストさせることができるので、これを利用して2017/02~2018/01の01日の日付を生成する
[root@BS-PUB-CENT7-01 ~]# printf "%s\n" 20{17/{02..12},18/01}/01
2017/02/01
2017/03/01
2017/04/01
2017/05/01
2017/06/01
2017/07/01
2017/08/01
2017/09/01
2017/10/01
2017/11/01
2017/12/01
2018/01/01
[root@BS-PUB-CENT7-01 ~]#
[root@BS-PUB-CENT7-01 ~]# # 上と組み合わせて、printfで実行するコマンドを一覧で出力させる
[root@BS-PUB-CENT7-01 ~]# printf 'faketime %s date -d "last fri"\n' 20{17/{02..12},18/01}/01
faketime 2017/02/01 date -d "last fri"
faketime 2017/03/01 date -d "last fri"
faketime 2017/04/01 date -d "last fri"
faketime 2017/05/01 date -d "last fri"
faketime 2017/06/01 date -d "last fri"
faketime 2017/07/01 date -d "last fri"
faketime 2017/08/01 date -d "last fri"
faketime 2017/09/01 date -d "last fri"
faketime 2017/10/01 date -d "last fri"
faketime 2017/11/01 date -d "last fri"
faketime 2017/12/01 date -d "last fri"
faketime 2018/01/01 date -d "last fri"
[root@BS-PUB-CENT7-01 ~]#
[root@BS-PUB-CENT7-01 ~]# # 生成したコマンドをパイプでシェルに渡して実行させる
[root@BS-PUB-CENT7-01 ~]# printf 'faketime %s date -d "last fri"\n' 20{17/{02..12},18/01}/01 | sh
2017年  1月 27日 金曜日 00:00:00 JST
2017年  2月 24日 金曜日 00:00:00 JST
2017年  3月 31日 金曜日 00:00:00 JST
2017年  4月 28日 金曜日 00:00:00 JST
2017年  5月 26日 金曜日 00:00:00 JST
2017年  6月 30日 金曜日 00:00:00 JST
2017年  7月 28日 金曜日 00:00:00 JST
2017年  8月 25日 金曜日 00:00:00 JST
2017年  9月 29日 金曜日 00:00:00 JST
2017年 10月 27日 金曜日 00:00:00 JST
2017年 11月 24日 金曜日 00:00:00 JST
2017年 12月 29日 金曜日 00:00:00 JST

2.Faketimeを用いない場合

さて、じゃあFaketimeを使わない場合だとどうすればよいのか。
dateでは出力フォーマットを指定できるので、それを使って月の金曜日で最後の日付を抽出してやればよい。
とりあえず、こんな感じ。

echo 17{12..01}{31..01}$'\n' | date -f - "+%F %m %w" 2>&- | awk '$3~ /5/ && !a[$2$3]++{print $1}' | tac

 

分解するとこんな感じ。

# ブレース展開で(存在しない日付を含む)1年間すべての日付を取得する
echo 2017/{12..01}/{31..01}$'\n'

# パイプで渡してやり、"YYYY-MM-DD MM 曜日(番号(金曜は5))"の形式で出力する。なお、「2>&-」は「2>/dev/null」と同様の動作をする
echo 2017/{12..01}/{31..01}$'\n' | date -f - "+%F %m %w" 2>&-

# awkを使って、3列目(曜日)が5のもののみを抽出する
echo 2017/{12..01}/{31..01}$'\n' | date -f - "+%F %m %w" 2>&- | awk '$3~ /5/'

# さらにawkに条件を追加して、2列目と3列目が同じものを以後表示させない
echo 2017/{12..01}/{31..01}$'\n' | date -f - "+%F %m %w" 2>&- | awk '$3~ /5/ && !a[$2$3]++'

# printで1列目のみを表示させるようにする
echo 2017/{12..01}/{31..01}$'\n' | date -f - "+%F %m %w" 2>&- | awk '$3~ /5/ && !a[$2$3]++{print $1}'

# 降順で日付を出力させていたので、tacで昇順にする
echo 2017/{12..01}/{31..01}$'\n' | date -f - "+%F %m %w" 2>&- | awk '$3~ /5/ && !a[$2$3]++{print $1}' | tac

 

実行結果。

[root@BS-PUB-CENT7-01 ~]# echo 2017/{12..01}/{31..01}$'\n' | date -f - "+%F %m %w" 2>&- | awk '$3~ /5/ && !a[$2$3]++{print $1}' | tac
2017-01-27
2017-02-24
2017-03-31
2017-04-28
2017-05-26
2017-06-30
2017-07-28
2017-08-25
2017-09-29
2017-10-27
2017-11-24
2017-12-29

 

その他の解き方としては、@Heliac1999さんのweek数とかこっちのやり方、@ebanさんのこれとかこれがとても参考になる。
…プレミアムフライデー、効果はどうかわからないけど、一般的になれば早く帰れるのでありがたいですね。

 

Image may be NSFW.
Clik here to view.
暦の科学 (BERET SCIENCE)
暦の科学 (BERET SCIENCE)

bashの標準出力・標準エラー出力リダイレクトの省略記述

よくbashやzshでシェル芸(ワンライナー)を書いてたりすると、標準エラー出力だけを/dev/nullに出力させたりといった処理を行う。
で、毎回いちいち/dev/nullとか指定するのもあれなんで、省略記述方法ないかなと思って調べてみたところ、Bash4以降だと結構記述方法が増えたようだ。個人的によく利用する記述の省略形だけピックアップして記述しておく。

2> /dev/null

標準エラー出力や標準出力、どっちかだけを非表示にさせたい場合だと「2>/dev/null」と記述して/dev/nullにリダイレクトさせるのだが、以下のようにも書けるようだ。

2>/dev/null
2>&-
blacknon@BS-PUB-UBUNTU-01:~$ ls -la aaa a
ls: 'a' にアクセスできません: そのようなファイルやディレクトリはありません
-rw-rw-r-- 1 blacknon blacknon 254  3月 13  2016 aaa
blacknon@BS-PUB-UBUNTU-01:~$
blacknon@BS-PUB-UBUNTU-01:~$ ls -la aaa a 2>/dev/null
-rw-rw-r-- 1 blacknon blacknon 254  3月 13  2016 aaa
blacknon@BS-PUB-UBUNTU-01:~$
blacknon@BS-PUB-UBUNTU-01:~$ ls -la aaa a 2>&-
-rw-rw-r-- 1 blacknon blacknon 254  3月 13  2016 aaa
blacknon@BS-PUB-UBUNTU-01:~$
blacknon@BS-PUB-UBUNTU-01:~$ ls -la \-
ls: '-' にアクセスできません: そのようなファイルやディレクトリはありません

2>&1 | Command …

標準エラー出力も含めてパイプで次のコマンドに渡す場合。
以下のようにも記述できる。

2&>1 | Command ...
|& Command ...
blacknon@BS-PUB-UBUNTU-01:~$ ls -la aaa a 2>&1 | grep -e ls -e $
ls: 'a' にアクセスできません: そのようなファイルやディレクトリはありません
-rw-rw-r-- 1 blacknon blacknon 254  3月 13  2016 aaa
blacknon@BS-PUB-UBUNTU-01:~$
blacknon@BS-PUB-UBUNTU-01:~$ ls -la aaa a |& grep -e ls -e $
ls: 'a' にアクセスできません: そのようなファイルやディレクトリはありません
-rw-rw-r-- 1 blacknon blacknon 254  3月 13  2016 aaa

 

同様の考え方で、「>&」で1,2ともにリダイレクトが行える。

 

cat /dev/null > Path

「/dev/null」からリダイレクトをして空ファイルを作ったり中身を削除する場合。
こういった場合は、以下のようにも書けるようだ。「:」はヌルコマンドなので、それを利用すればよい。

cat /dev/null > Path
: > Path
blacknon@BS-PUB-UBUNTU-01:~$ grep "" a_test{1,2}.txt
a_test1.txt:test
a_test2.txt:test
blacknon@BS-PUB-UBUNTU-01:~$
blacknon@BS-PUB-UBUNTU-01:~$ cat /dev/null > a_test1.txt
blacknon@BS-PUB-UBUNTU-01:~$ cat a_test1.txt
blacknon@BS-PUB-UBUNTU-01:~$
blacknon@BS-PUB-UBUNTU-01:~$ : > a_test2.txt
blacknon@BS-PUB-UBUNTU-01:~$ cat a_test2.txt

 

大体、こんなとこだろうか。
結構省略して書くことができるみたいだ。

 

【参考】

 

Image may be NSFW.
Clik here to view.
Windows/Mac/UNIX すべてで20年動くプログラムはどう書くべきか 一度書けばどこでも、ずっと使えるプログラムを待ち望んでいた人々へ贈る[シェルスクリプトレシピ集]
Windows/Mac/UNIX すべてで20年動くプログラムはどう書くべきか 一度書けばどこでも、ずっと使えるプログラムを待ち望んでいた人々へ贈る[シェルスクリプトレシピ集]

bash/zshでhistoryに任意の文字列を追加する

bashやzshで、historyに任意のコマンド…というか文字列を実行せずに追記したい場合。
それぞれ、以下のコマンドで行うことができるようだ。

history -s string # bashの場合
print -S string # zshの場合

blacknon@BS-PUB-UBUNTU-01:~$ history | tail
 1628  rm -rf ./*
 1629  clear
 1630  ls
 1631  echo aaa | tee test{01..20}.txt >& /dev/null
 1632  ls
 1633  grep '' ./*
 1634  clear
 1635  cd
 1636  clear
 1637  history | tail
blacknon@BS-PUB-UBUNTU-01:~$ history -s aaaa
blacknon@BS-PUB-UBUNTU-01:~$ history | tail
 1630  ls
 1631  echo aaa | tee test{01..20}.txt >& /dev/null
 1632  ls
 1633  grep '' ./*
 1634  clear
 1635  cd
 1636  clear
 1637  history | tail
 1638  aaaa
 1639  history | tail

 

Image may be NSFW.
Clik here to view.
[改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる (WEB+DB PRESS plus)
[改訂第3版]シェルスクリプト基本リファレンス ──#!/bin/shで、ここまでできる (WEB+DB PRESS plus)

clocコマンドで指定したディレクトリ配下のソースコードの種類とステップ数・カウント数や空行の数などを求める

特定のディレクトリ配下にあるファイルの行数とかを再帰的に取得する場合、wcコマンドが利用される場合が多いだろう。

wc -l $(find /PATH -type f)
blacknon@BS-PUB-UBUNTU-01:~/test_dir$ ls -la
合計 152
drwxrwxr-x 12 blacknon blacknon   4096  2月 25 16:42 .
drwxr-xr-x 15 blacknon blacknon   4096  2月 25 16:39 ..
drwxrwxr-x  2 blacknon blacknon   4096  2月 25 16:41 00
drwxrwxr-x  2 blacknon blacknon   4096  2月 25 16:41 10
drwxrwxr-x  2 blacknon blacknon   4096  2月 25 16:41 20
drwxrwxr-x  2 blacknon blacknon   4096  2月 25 16:42 30
drwxrwxr-x  2 blacknon blacknon   4096  2月 25 16:42 40
drwxrwxr-x  2 blacknon blacknon   4096  2月 25 16:42 50
drwxrwxr-x  2 blacknon blacknon   4096  2月 25 16:42 60
drwxrwxr-x  2 blacknon blacknon   4096  2月 25 16:42 70
drwxrwxr-x  2 blacknon blacknon   4096  2月 25 16:42 80
drwxrwxr-x  2 blacknon blacknon   4096  2月 25 16:42 90
-rw-rw-r--  1 blacknon blacknon 102773  2月 25 16:42 text.txt
blacknon@BS-PUB-UBUNTU-01:~/test_dir$ wc -l $(find ./ -type f)
    9344 ./40/test46.txt
    9344 ./40/test47.txt
    9344 ./40/test44.txt
    9344 ./40/test48.txt
    9344 ./40/test49.txt
        ~省略~
    9344 ./80/test89.txt
    9344 ./80/test82.txt
    9344 ./80/test85.txt
    9344 ./80/test83.txt
    9344 ./text.txt
  934400 合計

こんな感じでやれば、指定したディレクトリ配下にある各ファイルと合計の行数がわかる。
が、さらにその中身(ファイルの種類だったり、コメント行の行数だったり…)を把握する場合は、clocコマンドを利用すると楽だ。

インストールは、以下のコマンドで行える。

yum enablerepo=epel install cloc
apt install cloc
brew install cloc

 

インストール後は、普通に対象のディレクトリを引数として指定してやれば再帰的に確認してくれる。
出力例は以下。Golangとかでもちゃんと検知してくれる。

blacknon@BS-PUB-DEVELOP:~/go/src/github.com/blacknon/lssh$ cloc /home/blacknon/go/src
     373 text files.
     364 unique files.
     779 files ignored.

http://cloc.sourceforge.net v 1.60  T=2.05 s (161.7 files/s, 38455.4 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Go                             309           8222           6908          55065
Assembly                        15            613            390           7383
C                                1             37              8            152
Python                           1             15              1             94
YAML                             3              0              0             32
make                             1              5              0             14
C/C++ Header                     1              2              5              1
vim script                       1              0              0              1
-------------------------------------------------------------------------------
SUM:                           332           8894           7312          62742
-------------------------------------------------------------------------------

 

出力フォーマットも種類があって、xmlやcsvで出力させることも可能。
いまだにステップ数とかで成果を見てるとこなんかでは結構便利かもしれない(たぶんまだ生き残っている)。

 

Image may be NSFW.
Clik here to view.
かんたん Perl (プログラミングの教科書)
かんたん Perl (プログラミングの教科書)

コンソールでコマンドの結果を複数のファイルに結果をリダイレクトしたい場合

コンソール上で、コマンドの結果を複数のファイルに出力したいことがある。
そういった場合、残念ながらbashの場合、リダイレクトだと複数のファイルへ同時に書き込むといったことは難しい。じゃ、どうすればいいのかというと、teeコマンドであれば複数ファイルを指定できるので、それで対応する。

コマンド | tee ファイル1 ファイル2 ファイル3 ...  >& /dev/null # 追記しない場合
コマンド | tee -a ファイル1 ファイル2 ファイル3 ...  >& /dev/null # 追記する場合

blacknon@BS-PUB-UBUNTU-01:~/test_dir$ ls
blacknon@BS-PUB-UBUNTU-01:~/test_dir$ echo aaa | tee test{01..20}.txt >& /dev/null
blacknon@BS-PUB-UBUNTU-01:~/test_dir$ ls
test01.txt  test04.txt  test07.txt  test10.txt  test13.txt  test16.txt  test19.txt
test02.txt  test05.txt  test08.txt  test11.txt  test14.txt  test17.txt  test20.txt
test03.txt  test06.txt  test09.txt  test12.txt  test15.txt  test18.txt
blacknon@BS-PUB-UBUNTU-01:~/test_dir$ grep '' ./*
./test01.txt:aaa
./test02.txt:aaa
./test03.txt:aaa
./test04.txt:aaa
./test05.txt:aaa
./test06.txt:aaa
./test07.txt:aaa
./test08.txt:aaa
./test09.txt:aaa
./test10.txt:aaa
./test11.txt:aaa
./test12.txt:aaa
./test13.txt:aaa
./test14.txt:aaa
./test15.txt:aaa
./test16.txt:aaa
./test17.txt:aaa
./test18.txt:aaa
./test19.txt:aaa
./test20.txt:aaa

 

なお、zshの場合は以下のように複数ファイルを指定してのリダイレクトが可能になっている。

BS-PUB-UBUNTU-01% echo $0
zsh
BS-PUB-UBUNTU-01% ls
BS-PUB-UBUNTU-01% echo aaa > test_{01..20}.txt
BS-PUB-UBUNTU-01% ls
test_01.txt  test_04.txt  test_07.txt  test_10.txt  test_13.txt  test_16.txt  test_19.txt
test_02.txt  test_05.txt  test_08.txt  test_11.txt  test_14.txt  test_17.txt  test_20.txt
test_03.txt  test_06.txt  test_09.txt  test_12.txt  test_15.txt  test_18.txt
BS-PUB-UBUNTU-01% grep "" test_*
test_01.txt:aaa
test_02.txt:aaa
test_03.txt:aaa
test_04.txt:aaa
test_05.txt:aaa
test_06.txt:aaa
test_07.txt:aaa
test_08.txt:aaa
test_09.txt:aaa
test_10.txt:aaa
test_11.txt:aaa
test_12.txt:aaa
test_13.txt:aaa
test_14.txt:aaa
test_15.txt:aaa
test_16.txt:aaa
test_17.txt:aaa
test_18.txt:aaa
test_19.txt:aaa
test_20.txt:aaa

 

Image may be NSFW.
Clik here to view.
新しいLinuxの教科書
新しいLinuxの教科書

Apacheのログをsyslog(rsyslog)で管理する

Apacheのアクセスログやエラーログだが、デフォルトではSyslogは経由しない。
これらをSyslogを使って管理する場合、httpd.confに設定の追加が必要になる。

設定自体は簡単で、CustomLog/ErrorLogの設定に対して、パイプで繋げてloggerでSyslogに流すだけだ。
以下、設定の記述例(VirtualHostとか設定してると記述先のファイルも変わるので、自分の環境に合わせて記述すること)。CentOS 7で確認をしている。

●/etc/httpd/conf/httpd.conf

CustomLog "|/usr/bin/logger -p local5.info -t httpd_access" combined
ErrorLog  "|/usr/bin/logger -p local6.info -t httpd_error"

次に、rsyslog側でログの出力先を設定する。
リモートに転送するのであればそのように記述してやればよい。

●/etc/rsyslog.d/httpd.conf

local5.* /var/log/httpd/access_log
local6.* /var/log/httpd/error_log

 

さらに、今の設定のままだと/var/log/messagesにも同様のログが出力されてしまうので、/etc/rsyslog.confでmessagesへのログ出力設定に追記をする。

*.info;mail.none;authpriv.none;cron.none;local5.none;local6.none;
                                                        /var/log/messages

 

以上で設定は完了。
あとは、サービスの再起動をして設定を適用すればよい。

 

Image may be NSFW.
Clik here to view.
Apache Cookbook: Solutions and Examples for Apache Administration
Apache Cookbook: Solutions and Examples for Apache Administration

Nginxのログをsyslog(rsyslog)で管理する

Nginxのログをsyslogで管理する場合、Niginx 1.7.1以降であればaccess_logおよびerror_logがSyslogをサポートするようになっている。
2017年3月現在、aptや(Epel経由にはなるが)yumでインストールできるNginxは1.7.1以降になるので、その前提で進めていく。

設定自体は簡単で、Nginxの設定ファイルでaccess_log/error_logの設定を以下のように書き換えてやればよい。
ただ、ローカル内のSyslogへ転送する場合でもUDP経由で送る必要がある(上にtcpで直接リモートのサーバには転送できない)ので、事前にrsyslogの設定でudpからのログを受信するよう設定しておくこと。

●/etc/nginx/nginx.conf(ローカルのrsyslogに送る場合)

http {
    ...
    access_log syslog:server=127.0.0.1:514,facility=local7,tag=nginx,severity=info;
    ...

 

あとはまぁ、もろもろrsyslogの設定するだけなので割愛。

【参考】

 

Image may be NSFW.
Clik here to view.
nginx実践入門 (WEB+DB PRESS plus)
nginx実践入門 (WEB+DB PRESS plus)

rsyslogで特定のファシリティのログ(localファシリティとか)が/var/log/messagesに出力されないようにする

CentOSやUbuntuといった主要ディストリだと、Syslogにはrsyslogが使われている(ので、rsyslogがよく使われていると思う)。
でまぁ、rsyslogでlocalファシリティ(local5.infoとか)の設定をして、ファシリティ別に別ファイルにログを送るようにrsyslogで設定する際、以下の記述をしてないと「/var/log/messages」とか「/var/log/syslog」にもログが飛んでしまう。

*.info;mail.none;authpriv.none;cron.none;local5.none;local6.none;ファシリティ名.none;
                                                        /var/log/messages

 

これで、/var/log/messagesに対象のファシリティのログが転送されないようになったはずだ。

 

Image may be NSFW.
Clik here to view.
rsyslog 実践ログ管理入門
rsyslog 実践ログ管理入門

bashでコマンドをアスキーコードで記述して実行させる

Twitterでそういうのを試みてる人がいて、できるみたいだったので備忘。
bash/zshだと、『$’AsciiCode’』で記述してやるとアスキーコードをその場で直接展開してくれるらしい(知らなかった…)。

[root@BS-PUB-CENT7-01 ~]# echo $'\x6c\x6f\x67\x67\x65\x72\x20\x27\x48\x65\x6c\x6c\x6f\x27'
logger 'Hello'

 

で、これをそのまま実行するとコマンドが実行できるのかというと、どうもそうではないらしい。
教えていただいた内容によると、アスキーコードから展開させた場合だと、その結果はシングルクォートで括られた状態で扱われるらしく、アスキーコードでスペースを指定しててもあまり意味がないらしい。なので、実行するにはevalを利用するか、もしくはスペースだけはアスキーコードから展開させず、そのまま記述してやるといいみたいだ。アスキーコードの中でシングルクォートを指定してる場合、エスケープされたことと同じになってしまうので、evalとは結果が少し違う。

eval $'\x6c\x6f\x67\x67\x65\x72\x20\x27\x48\x65\x6c\x6c\x6f\x27'
$'\x6c\x6f\x67\x67\x65\x72' $'\x27\x48\x65\x6c\x6c\x6f\x27'
blacknon@BS-PUB-UBUNTU-01:~$ echo $'\x6c\x6f\x67\x67\x65\x72\x20\x27\x48\x65\x6c\x6c\x6f\x27'
logger 'Hello'
blacknon@BS-PUB-UBUNTU-01:~$ $'\x6c\x6f\x67\x67\x65\x72\x20\x27\x48\x65\x6c\x6c\x6f\x27'
logger 'Hello': コマンドが見つかりません
blacknon@BS-PUB-UBUNTU-01:~$
blacknon@BS-PUB-UBUNTU-01:~$ eval $'\x6c\x6f\x67\x67\x65\x72\x20\x27\x48\x65\x6c\x6c\x6f\x27'
blacknon@BS-PUB-UBUNTU-01:~$ $'\x6c\x6f\x67\x67\x65\x72' $'\x27\x48\x65\x6c\x6c\x6f\x27'
blacknon@BS-PUB-UBUNTU-01:~$ tail -2 /var/log/syslog
Feb 28 07:42:18 BS-PUB-UBUNTU-01 blacknon: Hello
Feb 28 07:42:27 BS-PUB-UBUNTU-01 blacknon: 'Hello'

手動でこのアスキーコード出すのは面倒(スペースをそのまま使うのであればなお)なので、文字列からアスキーコードを生成する場合は以下のようにコマンドを実行してやればよいだろう。

echo -n 'echo abc' | od -An -tx1 | sed 's/ /\\x/g;s/[^ ][^ ]*/eval \$'\''&'\''/g' # eval方式で出力
echo -n 'echo abc' | od -An -tx1 | sed 's/ /\\x/g;s/\\x20/ /g;s/[^ ][^ ]*/\$'\''&'\''/g' # そのまま実行可能な形式で出力
blacknon@BS-PUB-UBUNTU-01:~$ echo -n 'echo abc' | od -An -tx1 | sed 's/ /\\x/g;s/[^ ][^ ]*/eval \$'\''&'\''/g'
eval $'\x65\x63\x68\x6f\x20\x61\x62\x63'
blacknon@BS-PUB-UBUNTU-01:~$ echo -n 'echo abc' | od -An -tx1 | sed 's/ /\\x/g;s/[^ ][^ ]*/eval \$'\''&'\''/g' | bash
abc
blacknon@BS-PUB-UBUNTU-01:~$
blacknon@BS-PUB-UBUNTU-01:~$ echo -n 'echo abc' | od -An -tx1 | sed 's/ /\\x/g;s/\\x20/ /g;s/[^ ][^ ]*/\$'\''&'\''/g'
$'\x65\x63\x68\x6f' $'\x61\x62\x63'
blacknon@BS-PUB-UBUNTU-01:~$ echo -n 'echo abc' | od -An -tx1 | sed 's/ /\\x/g;s/\\x20/ /g;s/[^ ][^ ]*/\$'\''&'\''/g' | bash
abc

 

はー…
そもそも、こういったことをするという発想がなかったので、「できるんだなぁ…」という感想。
難読化という意味では確かに有用かもしれない…。読めない。

 

Image may be NSFW.
Clik here to view.
シェルプログラミング実用テクニック
シェルプログラミング実用テクニック

sed/awkで各文字列をシングルクォーテーション・ダブルクォーテーションで囲む

コンソール上でスペース区切りになっている各文字列をシングルクォーテーション・ダブルクォーテーションで囲みたいことがあったので、その対応について備忘。
以下のようにコマンドを実行することで、スペース区切りの各単語を囲むことができる。

sedの場合

sedで各単語を囲む場合、以下のようにコマンドを実行する。

sed 's/[^ ]\+/"&"/g' # ダブルクォーテーションの場合
sed 's/[^ ]\+/'\''&'\''/g' # シングルクォーテーションの場合
blacknon@BS-PUB-UBUNTU-01:~$ echo abc def 123 ABC | sed 's/[^ ]\+/"&"/g'
"abc" "def" "123" "ABC"
blacknon@BS-PUB-UBUNTU-01:~$ echo abc def 123 ABC | sed 's/[^ ]\+/'\''&'\''/g'
'abc' 'def' '123' 'ABC'

awkの場合

awkの場合だとこんな感じ。

awk '{for(i=1;i<=NF;i++)printf("\""$i"\" ")}END{printf("\n")}' # ダブルクォーテーションの場合
awk '{for(i=1;i<=NF;i++)printf("'\''"$i"'\'' ")}END{printf("\n")}' # シングルクォーテーションの場合
blacknon@BS-PUB-UBUNTU-01:~$ echo abc def ghi | awk '{for(i=1;i<=NF;i++)printf("\""$i"\" ")}END{printf("\n")}'
"abc" "def" "ghi"
blacknon@BS-PUB-UBUNTU-01:~$ echo abc def ghi | awk '{for(i=1;i<=NF;i++)printf("'\''"$i"'\'' ")}END{printf("\n")}'
'abc' 'def' 'ghi'

 

Image may be NSFW.
Clik here to view.
「シェル芸」に効く!AWK処方箋
「シェル芸」に効く!AWK処方箋

『響け!ユーフォニアム』のシェル芸を床屋のアレみたいに動かしてみる

まぁ、なんとなく。
ちょっと前にはやってた、『響け!ユーフォミアム』の文字列をループで1文字づつずらしてくシェル芸なのだが、なんかこう…床屋の前にあるくるくる回ってるポールみたいな奴(サインポールっていうらしい)のようにアニメーションさせられないかなと思いついたので、とりあえずやってみた。わかりやすいよう、「響」だけgrepで色つけてる。

echo 響け!ユーフォニアム|gsed ':a;p;s/\(.\)\(.*\)/\2\1/;ba'|xargs -I@ bash -c 'clear;echo @|gsed -ne"p;s/\(.\)\(.*\)/\2\1/;#"{0..9}|grep --color=always 響;sleep 0.1' # MacOS Xの場合
echo 響け!ユーフォニアム|sed ':a;p;s/\(.\)\(.*\)/\2\1/;ba'|xargs -I@ bash -c 'clear;echo @|sed -ne"p;s/\(.\)\(.*\)/\2\1/;#"{0..9}|grep --color=always 響;sleep 0.1' # Linuxの場合

Image may be NSFW.
Clik here to view.

 

更に、先日のアスキーコードでの実行などを使って、難読化させてみた。

echo ZWNobyDpn7/jgZHvvIHjg6bjg7zjg5Xjgqnjg4vjgqLjg6B8Z3NlZCAnOmE7cDtzL1woLlwpXCguKlwpL1wyXDEvO2JhJ3x4YXJncyAtSUAgYmFzaCAtYyAnY2xlYXI7ZWNobyBAfGdzZWQgLW5lInA7cy9cKC5cKVwoLipcKS9cMlwxLzsjInswLi45fXxncmVwIC0tY29sb3I9YWx3YXlzIOmfvztzbGVlcCAwLjEnCg== | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x44' | $'\x73\x68' # MacOS X用
echo ZWNobyDpn7/jgZHvvIHjg6bjg7zjg5Xjgqnjg4vjgqLjg6B8c2VkICc6YTtwO3MvXCguXClcKC4qXCkvXDJcMS87YmEnfHhhcmdzIC1JQCBiYXNoIC1jICdjbGVhcjtlY2hvIEB8c2VkIC1uZSJwO3MvXCguXClcKC4qXCkvXDJcMS87IyJ7MC4uOX18Z3JlcCAtLWNvbG9yPWFsd2F5cyDpn787c2xlZXAgMC4xJwo= | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' | $'\x73\x68' # Linux用

Image may be NSFW.
Clik here to view.

 

前に触ったcoloutを使って、「響」だけじゃなく、各文字に色つけてカラフルに?してみたのもある。
(ちょっと描写遅いけど)

echo 響け!ユーフォニアム|sed ':a;p;s/\(.\)\(.*\)/\2\1/;ba'|xargs -I@ bash -c 'clear;echo @|sed -ne"p;s/\(.\)\(.*\)/\2\1/;#"{0..9}|colout "(響*)(け*)(!*)(ユ*)(ー*)(フ*)(ォ*)(ニ*)(ア*)(ム*)" 1,2,3,4,5,6,7,8,9,14;sleep 0.5'

Image may be NSFW.
Clik here to view.

 

Image may be NSFW.
Clik here to view.
サインポール EASYサイン グレー バーバー 50Hz
サインポール EASYサイン グレー バーバー 50Hz

自身のローカルネットワークアドレスをCIDR形式で取得する

会社で同僚と会話中、こういった話題になったので”そういや、どうやって取るんだろ”と思って調べてみた。
結果、専用のコマンドでどうにかするってのは厳しそうだったので、ipcalcおよびsipcalcを使って計算、取得させてみた。

ipcalc $(ip addr show en0 | awk '$1=="inet"{print $2}') | awk 'NR==5{print $2}'
sipcalc en0 | awk -F- '/Network address/||/Network mask \(bits\)/{print $2}' | xargs | sed 's/ /\//g'
blacknon@BS-PUB-DEVELOP:~$ ipcalc $(ip addr show ens18 | awk '$1=="inet"{print $2}') | awk 'NR=
=5{print $2}'
172.28.0.0/24
blacknon@BS-PUB-DEVELOP:~$ sipcalc ens18 | awk -F- '/Network address/||/Network mask \(bits\)/{
print $2}' | xargs | sed 's/ /\//g'
172.28.0.0/24

 

Image may be NSFW.
Clik here to view.
Windows/Mac/UNIX すべてで20年動くプログラムはどう書くべきか 一度書けばどこでも、ずっと使えるプログラムを待ち望んでいた人々へ贈る[シェルスクリプトレシピ集]
Windows/Mac/UNIX すべてで20年動くプログラムはどう書くべきか 一度書けばどこでも、ずっと使えるプログラムを待ち望んでいた人々へ贈る[シェルスクリプトレシピ集]

Apache GuacamoleでsshやRDP接続時の操作を記録する(テキストor動画)

以前にも触れたことのある、HTML5の踏み台サーバであるApache Guacamole。ssh接続時のターミナル操作のログを記録することもできるため、今回はそれを行う。取得できるログは2種類で、「Typescript(テキストベース)」および「Screen Recording(動画で取得)」のパターン。当たり前ではあるのだが、テキストベースはsshやtelnetでしか取れない。
今回利用するGuacamoleのバージョンは0.9.9とする。0.9.9の場合、テキストやビデオでの操作ログの取得は簡単で、Webの設定画面から行える。

Guacamoleでは、接続先ごとにログを記録するかどうか、記録先のPATHやログ名の設定が行える。
[SETTINGS] > [Connections]から対象のサーバの設定画面を開いて、[PARAMETERS]で対象の設定を行う。以下の画面はssh接続の場合。

Image may be NSFW.
Clik here to view.

 

それぞれの設定項目は簡単で、以下のようになっている。

  • (Typescript|Recording) path: … ログや録画したデータを配置するディレクトリ
  • (Typescript|Recording) name: … ログや録画したデータの名称
  • Automatically create (typescript|recording) path: … 指定された配置先ディレクトリを自動的に作成するかどうか

ちなみに、こちらにあるように配置先ディレクトリやファイル名には変数が利用できる。
残念ながら接続先のホスト名は変数で用意されていない様子。設定自体が接続先ごとに行われるから、それでどうにかするって感じだろうか。

  • ${GUAC_USERNAME} … 接続されたGuacamoleのユーザ名
  • ${GUAC_PASSWORD} … 接続されたGuacamoleユーザのパスワード(これいるの?使いどころが不明なのだが…)
  • ${GUAC_DATE} … 接続日(YYYYMMDD)
  • ${GUAC_TIME} … 接続時刻(HHMMSS)

 

というわけで、設定するログファイルの名称例としては、以下のようにするといいのかなと。

  • ${GUAC_DATE}-${GUAC_TIME}_接続先名_${GUAC_USERNAME}.log

 

上記設定を保存後は、接続したら自動的にログが出力されるようになる。

Image may be NSFW.
Clik here to view.

 

ちなみに、Screen Recordingの場合は一度ファイルを変換してm4vにすると再生できる。

guacenc 対象の録画データファイルPATH

 

変換後は、管理者がどこかに保管しておいて、随時閲覧すればよいだろう。
テキストよりも容量が大きくなるはずなので、退避を的確にしないといけないが、RDPやVNC接続であったとしても操作を記録できるのは素晴らしい。

 

[amazonjs asin=”B01IT509F8″ locale=”JP” title=”改訂新版 情報セキュリティ内部監査の教科書 (NextPublishing)”

Yahoo!PipeやIFTTTのように使える自動化ツール『Huginn』をUbuntu Server 16.04 LTSにインストールする

まえにStackStorm(St2)という、イベントドリブンな自動化ツール(特定のイベントが発生したら、指定された処理を自動で行ってくれるツール)を触ったことがあったのだが、それと同じように利用できそうな『Huggin』というツールを見かけた。Yahoo!PipeやIFTTTのような利用ができるらしい。
今回は、この『Huggin』をUbuntu Server 16.04 LTSにインストールしてみる。(Dockerもあるようなので、パッと試す場合はそちらでもいいだろう)

1.前提パッケージのインストール

まずは、以下のコマンドでupdateを行っておこう。

sudo apt-get update -y
sudo apt-get upgrade -y

 

Node.jsやその他必要になるパッケージをまとめてインストールする。
なお、Rubyは2.3以降が必要になるようなので、インストール完了後もしバージョンが古かったら別途インストールしなおす。

curl -sL https://deb.nodesource.com/setup_0.12 | sudo bash -
sudo dpkg-divert --local --rename --add /sbin/initctl
sudo ln -s /bin/true /sbin/initctl
sudo apt-get install -y runit build-essential git zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libreadline-dev libncurses5-dev libffi-dev curl openssh-server checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev logrotate python-docutils pkg-config cmake nodejs graphviz ruby ruby.h ruby-dev
sudo gem install rake bundler foreman --no-ri --no-rdoc

 

2.システムユーザの作成

Huginnを動作させるシステムユーザを作成する。

sudo adduser --disabled-login --gecos 'Huginn' huginn

 

3.データベースの作成

次に、データベースの作成をする。最初にパッケージの導入を行う。

sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev

 

rootユーザのパスワード設定など、最低限のセキュリティ設定を行う。

sudo mysql_secure_installation

 

ユーザやデータベースの作成を行う。

mysql -u root -p -e '
    CREATE USER "huginn"@"localhost" IDENTIFIED BY "huginn";
    SET default_storage_engine=INNODB;
    GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, LOCK TABLES ON `huginn_production`.* TO "huginn"@"localhost";'

 

この時点ではデータベースの作成は行わない。

4.Huginnのインストールを行う

ここまで終わったら、Huginnのインストールを行う。
以下のコマンドを実行し、ソースのダウンロード等を行う。

cd /home/huginn
sudo -u huginn -H git clone https://github.com/cantino/huginn.git -b master huginn
cd /home/huginn/huginn
sudo -u huginn -H cp .env.example .env
sudo -u huginn mkdir -p log tmp/pids tmp/sockets
sudo chown -R huginn log/ tmp/
sudo chmod -R u+rwX,go-w log/ tmp/
sudo chmod -R u+rwX,go-w log/
sudo chmod -R u+rwX tmp/
sudo -u huginn -H chmod o-rwx .env
sudo -u huginn -H cp config/unicorn.rb.example config/unicorn.rb

 

設定ファイル『.env』を以下のように編集する。

DATABASE_ADAPTER=mysql2
DATABASE_RECONNECT=true
DATABASE_NAME=huginn_production
DATABASE_POOL=20
DATABASE_USERNAME=huginn
DATABASE_PASSWORD='$password'
#DATABASE_HOST=your-domain-here.com
#DATABASE_PORT=3306
#DATABASE_SOCKET=/tmp/mysql.sock

DATABASE_ENCODING=utf8
# MySQL only: If you are running a MySQL server >=5.5.3, you should
# set DATABASE_ENCODING to utf8mb4 instead of utf8 so that the
# database can hold 4-byte UTF-8 characters like emoji.
#DATABASE_ENCODING=utf8mb4

RAILS_ENV=production

 

設定ファイル編集後、必要になるGemのインストールを行う。

sudo -u huginn -H bundle install --deployment --without development test

 

その他、データベースの作成などを行う。

sudo -u huginn -H bundle exec rake db:create RAILS_ENV=production
sudo -u huginn -H bundle exec rake db:migrate RAILS_ENV=production
sudo -u huginn -H bundle exec rake db:seed RAILS_ENV=production SEED_USERNAME=admin SEED_PASSWORD=password
sudo -u huginn -H bundle exec rake assets:precompile RAILS_ENV=production

 

『Procfile』ファイルで、以下のようにコメントアウトする行を変更する。

●/home/huginn/huginn/Procfile

# コメントアウトする
# web: bundle exec rails server -p ${PORT-3000} -b ${IP-0.0.0.0}
# jobs: bundle exec rails runner bin/threaded.rb

# コメントアウト解除
web: bundle exec unicorn -c config/unicorn.rb
jobs: bundle exec rails runner bin/threaded.rb

 

 

ファイル編集後、以下のコマンドを実行する。

sudo bundle exec rake production:export
sudo cp deployment/logrotate/huginn /etc/logrotate.d/huginn
sudo bundle exec rake production:status

 

5.Nginxをインストールする

最後に、フロントとして利用するNginxをインストールする。

sudo apt-get install -y nginx

 

aptでインストール後、以下のコマンドでHuginn用の設定ファイルを配置する。

sudo cp deployment/nginx/huginn /etc/nginx/sites-available/huginn
sudo ln -s /etc/nginx/sites-available/huginn /etc/nginx/sites-enabled/huginn
sudo rm /etc/nginx/sites-enabled/default

 

コンフィグテストを行い、サービスの起動を行う。

sudo nginx -t
sudo service nginx restart

 

6.ブラウザからアクセスする

さて、インストールや諸々の設定が終わったら、ブラウザからアクセスしてみよう。「http://サーバのホスト名orIPアドレス」でアクセスできる。

Image may be NSFW.
Clik here to view.

 

初期ID/PWは「admin/password」になっている。
ひとまず、今回はインストールまで。次回以降、実際の設定などを行っていこう。

 

 

Image may be NSFW.
Clik here to view.
DevOps導入指南 Infrastructure as Codeでチーム開発・サービス運用を効率化する
DevOps導入指南 Infrastructure as Codeでチーム開発・サービス運用を効率化する

ターミナル上でURLをブックマークする『Buku』

wgetやcurlなどで、よく利用するURLと言うのはあると思う。で、毎回historyから取ってくるのも面倒だなぁと思って調べてみたところ、コンソール上でよく使うURLをブックマークできるツール『Buku』というコマンドを見かけたので、ちょっと試してみた。

1.インストール

Python3で書かれているらしいので、事前に必要となるパッケージをインストールをしておく。

sudo apt install python3-cryptography python3-bs4 git
sudo yum install python3-cryptography python3-bs4 git

 

前提となるパッケージインストール後、以下のコマンドを実行して『Buku』のインストールを行う。

git clone https://github.com/jarun/Buku/
cd Buku
sudo make install

 

これでインストールができた。

2.使ってみる

さて、それでは実際に使ってみよう。
色々オプションがあるみたいなのだが、とりあえず以下を把握しておけばいいだろう。

buku -p # ブックマークリストを表示する
buku -a URL # ブックマークを追加する
buku -d N # 指定された番号のブックマークを削除する
buku -u N # 指定された番号のブックマークをアップデートする

 

残念ながら指定されたブックマークのURLのみを得ることはできないようなので、curlなどと組み合わせる場合はawkなどを利用して抽出してやる必要があるみたいだ。
以下の例では、1番のブックマークに対してcurlでアクセスしている。

curl $(buku -p 1 -f 1 | awk '{print $2}')

 

使いようによっては便利そうなツールだ。

 

Image may be NSFW.
Clik here to view.
データを集める技術 (Informatics &IDEA)
データを集める技術 (Informatics &IDEA)

 

awkでn回目にmutchした行のみを対象に処理を行う

awkで、n回目に条件にマッチした行のみに処理を行わせたいことがあったので、備忘として残しておく。
ちなみに、1回目ならこれでOK。

cat test1.txt | awk '/abc/{print $1;exit}'
blacknon@BS-PUB-UBUNTU-01:~$ cat test1.txt
1 abc
2 bbb
3 ccc
4 ddd
5 eee
6 fff
7 ggg
8 abc
9 bbb
blacknon@BS-PUB-UBUNTU-01:~$ cat test1.txt | awk '/abc/{print $1;exit}'
1

n回目なら、このように何回目のデ-タかを指定してやればいい。

cat test1.txt | awk '/abc/{i++}i==2{print $1;exit}'
blacknon@BS-PUB-UBUNTU-01:~$ cat test1.txt
1 abc
2 bbb
3 ccc
4 ddd
5 eee
6 fff
7 ggg
8 abc
9 bbb
blacknon@BS-PUB-UBUNTU-01:~$ cat test1.txt | awk '/abc/{i++}i==2{print $1;exit}'
8

 

Image may be NSFW.
Clik here to view.
「シェル芸」に効く!AWK処方箋
「シェル芸」に効く!AWK処方箋

whoisコマンドでドメインの有効期限のみを取得する

諸事情により、ドメインの有効期限についてスクリプトで取得する必要が出てきたので、取得方法について残しておく。LinuxやMac OS Xの場合、whoisコマンドでドメインのwhois情報が得られるので、そこからドメイン有効期限を取得する。ドメインの種類によってwhoisの出力内容は異なり、有効期限の表示方法も変わってくる。
以下、一般的によく利用されるドメインの種類別での取得方法(google.~で確認している)。

whois google.co.jp | sed -n '/状態/s/^.*(\(.*\)).*$/\1/p'
whois google.jp | awk '/有効期限/{print $2}'
whois google.com | awk '/ Expiration Date/{print $3;exit}' | date +%Y/%m/%d -f -
whois google.net | awk '/ Expiration Date/{print $3;exit}' | date +%Y/%m/%d -f -
whois google.org | awk '/ Expiry Date/{print $4;exit}' | date +%Y/%m/%d -f -

blacknon@BS-PUB-UBUNTU-01:~$ whois google.co.jp | sed -n '/状態/s/^.*(\(.*\)).*$/\1/p'
2017/03/31
blacknon@BS-PUB-UBUNTU-01:~$ whois google.jp | awk '/有効期限/{print $2}'
2017/05/31
blacknon@BS-PUB-UBUNTU-01:~$ whois google.com | awk '/ Expiration Date/{print $3;exit}' | date +%Y/%m/%d -f -
2020/09/14
blacknon@BS-PUB-UBUNTU-01:~$ whois google.net | awk '/ Expiration Date/{print $3;exit}' | date +%Y/%m/%d -f -
2018/03/15
blacknon@BS-PUB-UBUNTU-01:~$ whois google.org | awk '/ Expiry Date/{print $4;exit}' | date +%Y/%m/%d -f -
2017/10/20

 

Image may be NSFW.
Clik here to view.
実践DNS DNSSEC時代のDNSの設定と運用
実践DNS DNSSEC時代のDNSの設定と運用

aproposコマンドで指定したキーワードを含むmanを検索する

今まで知らなかったのだが、『apropos』というコマンドで指定したキーワードを含むマニュアルをmanから検索することができるようだ。
というわけで、早速検索してみよう。

apropos キーワード

 

例えば、「find」というキーワードで検索した場合は以下。

Image may be NSFW.
Clik here to view.

[root@BS-PUB-CENT7-01 ~]# apropos find
BIO_find_type (3ssl) - BIO chain traversal
btrfs-find-root (8)  - filter to find btrfs root
dracut-initqueue.service (8) - runs the dracut main loop to find the real root
FcConfigFilename (3) - Find a config file
File::Find (3pm)     - Traverse a directory tree.
find (1)             - search for files in a directory hierarchy
find-jar (1)         - find extension JAR or directory
find2perl (1)        - translate find command lines to Perl code
FindBin (3pm)        - Locate directory of original perl script
findfs (8)           - find a filesystem by label or UUID
findmnt (8)          - find a filesystem
git-bisect (1)       - Find by binary search the change that introduced a bug
git-cherry (1)       - Find commits not merged upstream
git-merge-base (1)   - Find as good common ancestors as possible for a merge
git-name-rev (1)     - Find symbolic names for given revs
git-pack-redundant (1) - Find redundant pack files
mysql_find_rows (1)  - extract SQL statements from files
oldfind (1)          - search for files in a directory hierarchy
OPENSSL_ia32cap (3ssl) - finding the IA-32 processor capabilities
perlmodlib (1)       - constructing new Perl modules and finding existing ones
pidof (8)            - find the process ID of a running program.
Pod::Simple::Search (3pm) - find POD documents in directory trees
systemd-delta (1)    - Find overridden configuration files
XFindContext (3)     - associative look-up routines
XkbFindOverlayForKey (3) - Find the alternate name by using the primary name for a key that is part of an overlay
XkbGetControls (3)   - Finds the current state of Xkb server controls
XkbKeycodeToKeysym (3) - Finds the keysym bound to a particular key at a specified group and shift level
XkbKeysymToModifiers (3) - Finds the set of modifiers bound to a particular keysym on the core keyboard
XkbLookupKeyBinding (3) - Find the string bound to a key by XRebindKeySym
XkbLookupKeySym (3)  - Find the symbol associated with a key for a particular state
XkbTranslateKeySym (3) - Find the string and symbol associated with a keysym for a given keyboard state

 

オプションで正規表現での検索もできるようだ。今まで知らなかったけど、結構便利そうだ。

 

Image may be NSFW.
Clik here to view.
入門者のLinux 素朴な疑問を解消しながら学ぶ (ブルーバックス)
入門者のLinux 素朴な疑問を解消しながら学ぶ (ブルーバックス)
Viewing all 743 articles
Browse latest View live