Quantcast
Channel: CentOS –俺的備忘録 〜なんかいろいろ〜
Viewing all 498 articles
Browse latest View live

xargsライクにパラレルでコマンドを実行させる『machma』

$
0
0

ネットで調べ物中に、xargsみたいな使い方でパラレルでコマンドを実行させることができる『machma』なるコマンドツールを見かけたのでお試し。GNU拡張されたxargsの場合、並列でコマンドを実行させることができるのだが、実行結果の出力時に使用したパラメータを先頭に入れて表示してくれたりするので、使い勝手はこちらのほうが良いと思う。

Golangで記述されているので、まだGoのコンパイル環境がない場合は別途用意する必要がある。
環境が用意できたら、以下のコマンドでインストールを行う。

go get github.com/fd0/machma
go install github.com/fd0/machma

インストールができたら、実際に利用してみよう。
受付した値は「{}」で表現されるので、実行するコマンドで受け付けた値を差し込む箇所に入れてやる。とりあえず、サンプルにあるようにpingを実行してみる。

echo 172.20.100.1{18..21} | tr ' ' '\n' | machma -- sh -c 'ping -c 2 {}'
blacknon@BS-PUB-DEVELOP:~$ echo 172.20.100.1{18..21} | tr ' ' '\n' | machma -- sh -c 'ping -c 2 {}'
1 2017-05-30 09:03:42 172.20.100.118 PING 172.20.100.118 (172.20.100.118) 56(84) bytes of data.
1 2017-05-30 09:03:42 172.20.100.118 64 bytes from 172.20.100.118: icmp_seq=1 ttl=64 time=0.566 ms
2 2017-05-30 09:03:42 172.20.100.119 PING 172.20.100.119 (172.20.100.119) 56(84) bytes of data.
2 2017-05-30 09:03:42 172.20.100.119 64 bytes from 172.20.100.119: icmp_seq=1 ttl=64 time=0.638 ms
2 2017-05-30 09:03:43 172.20.100.119 64 bytes from 172.20.100.119: icmp_seq=2 ttl=64 time=0.617 ms
2 2017-05-30 09:03:43 172.20.100.119 --- 172.20.100.119 ping statistics ---
2 2017-05-30 09:03:43 172.20.100.119 2 packets transmitted, 2 received, 0% packet loss, time 999ms
2 2017-05-30 09:03:43 172.20.100.119 rtt min/avg/max/mdev = 0.617/0.627/0.638/0.027 ms
1 2017-05-30 09:03:43 172.20.100.118 64 bytes from 172.20.100.118: icmp_seq=2 ttl=64 time=0.463 ms
1 2017-05-30 09:03:43 172.20.100.118 --- 172.20.100.118 ping statistics ---
1 2017-05-30 09:03:43 172.20.100.118 2 packets transmitted, 2 received, 0% packet loss, time 1001ms
1 2017-05-30 09:03:43 172.20.100.118 rtt min/avg/max/mdev = 0.463/0.514/0.566/0.056 ms
4 2017-05-30 09:03:43 172.20.100.121 PING 172.20.100.121 (172.20.100.121) 56(84) bytes of data.
4 2017-05-30 09:03:43 172.20.100.121 64 bytes from 172.20.100.121: icmp_seq=1 ttl=64 time=0.515 ms
3 2017-05-30 09:03:43 172.20.100.120 PING 172.20.100.120 (172.20.100.120) 56(84) bytes of data.
3 2017-05-30 09:03:43 172.20.100.120 64 bytes from 172.20.100.120: icmp_seq=1 ttl=64 time=0.579 ms
4 2017-05-30 09:03:44 172.20.100.121 64 bytes from 172.20.100.121: icmp_seq=2 ttl=64 time=0.635 ms
4 2017-05-30 09:03:44 172.20.100.121 --- 172.20.100.121 ping statistics ---
4 2017-05-30 09:03:44 172.20.100.121 2 packets transmitted, 2 received, 0% packet loss, time 1001ms
4 2017-05-30 09:03:44 172.20.100.121 rtt min/avg/max/mdev = 0.515/0.575/0.635/0.060 ms
3 2017-05-30 09:03:44 172.20.100.120 64 bytes from 172.20.100.120: icmp_seq=2 ttl=64 time=0.559 ms
3 2017-05-30 09:03:44 172.20.100.120 --- 172.20.100.120 ping statistics ---
3 2017-05-30 09:03:44 172.20.100.120 2 packets transmitted, 2 received, 0% packet loss, time 1000ms
3 2017-05-30 09:03:44 172.20.100.120 rtt min/avg/max/mdev = 0.559/0.569/0.579/0.010 ms

processed 4 items (0 failures) in 0:02

 

タイムスタンプも出力してくれるし、受け付けたパラメータについてもちゃんと行ごとに出力してくれるので、かなり見やすい。
こりゃ便利だ。

 

プログラミング経験者がGo言語を本格的に勉強する前に読むための本 プログラミング経験者がGo言語を本格的に勉強する前に読むための本

Linuxで指定したユーザのホームディレクトリを取得する

$
0
0

Linuxで、特定のユーザのホームディレクトリを取得する場合、以下のようにコマンドを実行すると良いようだ。備忘として残しておく。

echo ~$USERNAME

[root@BS-PUB-CENT7-01 ~]# awk 'BEGIN{FS=OFS=":"}!/nologin/{print $1,$(NF-1)}' /etc/passwd
root:/root
sync:/sbin
shutdown:/sbin
halt:/sbin
sftp:/home/sftp
opt:/opt
aaa:/opt/home
[root@BS-PUB-CENT7-01 ~]# echo ~aaa
/opt/home
[root@BS-PUB-CENT7-01 ~]# echo ~root
/root
[root@BS-PUB-CENT7-01 ~]# echo ~sftp
/home/sftp

 

新しいLinuxの教科書 新しいLinuxの教科書

bashのブレース展開を使用した際の出力結果の区切りをsedなどで置換せずに空白から改行にする

$
0
0

bashのブレース展開を使用する際、その出力結果を改行して使いたい場合がある。
そんなときは、よくsedやtrでスペースを改行に置換してやったりするのだが、そういった置換処理をせずに改行で出力できないのかなと思ったので、ちょっと調べてみた。

とりあえず、以下の3通りの方法があるようだ。

printfを利用する

多分、一番扱いやすいのではなかろうか。
以下のように、printfの入力元の値を用いることで出力時に改行させることが可能だ。

printf "%s\n" test{01..10}
blacknon@BS-PUB-UBUNTU-01:~$ printf "%s\n" test{01..10}
test01
test02
test03
test04
test05
test06
test07
test08
test09
test10

evalを利用する

知らなかったのだが、evalで以下のようにブレース展開を行うことで、改行した状態にしてechoしてくれるらしい。
スペースをエスケープさせる必要があるのはちょっと面倒だけど、コレは面白い(処理速度はちょっと遅い気がするけど…)。

eval echo\ test{01..10}\;
blacknon@BS-PUB-UBUNTU-01:~$ eval echo\ test{01..10}\;
test01
test02
test03
test04
test05
test06
test07
test08
test09
test10
blacknon@BS-PUB-UBUNTU-01:~$
blacknon@BS-PUB-UBUNTU-01:~$ # こういうことらしい
blacknon@BS-PUB-UBUNTU-01:~$ eval echo echo\ test{01..10}\;
echo test01
test02
test03
test04
test05
test06
test07
test08
test09
test10

forを利用する

正直、1行でちゃちゃっとやるには使いにくいのだけど、forで回すと言った方法もある。

for i in test{1..10}; do echo $i; done
blacknon@BS-PUB-UBUNTU-01:~$ for i in test{1..10}; do echo $i; done
test1
test2
test3
test4
test5
test6
test7
test8
test9
test10

 

気にするほどでもないと思うが、それぞれの速度はこんな感じ。

blacknon@BS-PUB-UBUNTU-01:~$ time (printf "%s\n" test{00001..30000}>/dev/null)

real    0m0.060s
user    0m0.060s
sys     0m0.000s
blacknon@BS-PUB-UBUNTU-01:~$ time (eval echo\ test{00001..30000}\;>/dev/null)

real    0m0.332s
user    0m0.304s
sys     0m0.028s
blacknon@BS-PUB-UBUNTU-01:~$ time (for i in test{00001..30000}; do echo $i; done>/dev/null)

real    0m0.208s
user    0m0.192s
sys     0m0.016s
blacknon@BS-PUB-UBUNTU-01:~$ time (echo test{00001..30000}|tr ' ' '\n'>/dev/null)

real    0m0.058s
user    0m0.052s
sys     0m0.008s
blacknon@BS-PUB-UBUNTU-01:~$ time (echo test{00001..30000}|sed 's/ /\n/g' >/dev/null)

real    0m0.065s
user    0m0.064s
sys     0m0.004s

 

とりあえず、置換したくなければprintf使っておけば良いのかな。

シェルプログラミング実用テクニック シェルプログラミング実用テクニック

ターミナル上から指定した文字列のドメインが取得可能か確認する

$
0
0

ネットで調べ物をしていたところ、ターミナルから指定文字列でドメインが取得可能かどうかを確認できるという『dom』コマンドなるものを見かけたのだが、APIとか使って色々やらないといけないみたいで、ちょっと面倒そう。

で、whoisコマンドとかを使って同じようなことをできないかなと思ったので、試しにやってみた。
とりあえず、以下のようにコマンドを実行することで、まだ取得されていない.jpや.co.jp、.comドメインについて抽出できた。

printf "%s\n" orebibou.{jp,co.jp,com,net,org} | xargs -I@ -n1 bash -c '(whois @ | grep -iq -e "no match" -e "not found" && echo @)'
blacknon@BS-PUB-UBUNTU-01:~$ printf "%s\n" orebibou.{jp,co.jp,com,net,org} | xargs -I@ -n1 bash -c '(whois @ | grep -iq -e "no match" -e "not found" && echo @)'
orebibou.jp
orebibou.co.jp
orebibou.net
orebibou.org
blacknon@BS-PUB-UBUNTU-01:~$ printf "%s\n" orebibou1.{jp,co.jp,com,net,org} | xargs -I@ -n1 bash -c '(whois @ | grep -iq -e "no match" -e "not found" && echo @)'
orebibou1.jp
orebibou1.co.jp
orebibou1.com
orebibou1.net
orebibou1.org

 

まあ、たんにwhoisでデータのないドメイン抽出しているだけなんだけど…

 

イラスト図解式 この一冊で全部わかるWeb技術の基本 イラスト図解式 この一冊で全部わかるWeb技術の基本

ldapsearchでユーザ名・最終パスワード変更日の一覧を作成する

$
0
0

仕事とかでActive Directoryとかをいじったりするのだが、Windows ServerってPowerShellをリモートから操作できるようにしてないと、RDPでつなげてコマンドを打たなくてならず、色々とまどろっこしい事が多い。RDPで接続したとしても、GUIでリストの確認ができるのならまだ納得感はあるのだけど…。

で、やはりちょっと面倒だったりするので、UNIX環境からリモートで一覧を取得してやることにしたのだが、どうもLDAPで管理されている日付データというのが「1601/01/01 00:00:00からの経過時間を100ナノ秒単位」で表しているようで、そのままだと正直わけがわからない。
なので、とりあえず今回はawkを使って無理やり日付を読める形式に変換して、一覧にすることにした。今回はユーザ名・最終パスワード変更日を抽出している。

ldapsearch -x -D "cn=Administrator,cn=Users,dc=domain,dc=local"                \
           -W -H ldap://LDAP-SERVER -b "DC=domain,DC=local" cn pwdlastset | \
grep -e ^pwdLastSet -B1                                                        | \
awk '/^cn|^pwdLastSet/{if(/^pwdLastSet/ && $2!=0){print strftime("%Y-%m-%d_%H:%M:%S",int(($2/10000000)-11644473600))}else{print $2}}' | \
paste - - | column -t

$ ldapsearch -x -D "cn=Administrator,cn=Users,dc=blacknon,dc=local"                \
>            -W -H ldap://172.21.XXX.XXX -b "DC=blacknon,DC=local" cn pwdlastset | \
> grep -e ^pwdLastSet -B1                                                        | \
> awk '/^cn|^pwdLastSet/{if(/^pwdLastSet/ && $2!=0){print strftime("%Y-%m-%d_%H:%M:%S",int(($2/10000000)-11644473600))}else{print $2}}' | \
> paste - - | column -t
Enter LDAP Password:
FreeNAS         2016-09-18_11:40:10
krbtgt          2016-01-17_22:57:01
bs-pub-product  2016-05-15_23:20:56
Guest           0
Hime            2016-11-04_18:30:53
Redmine         2016-09-18_11:22:14
BS-PUB-DOMAINC  2016-01-17_22:57:01
Administrator   2017-06-03_09:56:30
Blacknon        2016-09-28_09:31:07
BS-PHY-STOR-01  2017-05-28_16:30:58

 

入門LDAP/OpenLDAPディレクトリサービス導入・運用ガイド第2版 入門LDAP/OpenLDAPディレクトリサービス導入・運用ガイド第2版

Linux/Macで並列でpingを実行して100台以上の疎通確認を数秒で終わらせる

$
0
0

特定のネットワークに対し、疎通確認や稼働しているホストを確認する場合、よく以下のようなforを使用して確認処理を行うことがある。

for a in `seq 1 254`; do ping -c 1 -w 0.5 対象セグメント(第3オクテットまで).$a > /dev/null && arp -a 対象セグメント(第3オクテットまで).$a | grep ether; done

 

ただ、コレってやはりちょっと扱いにくい上、1個づつping打ってくからやっぱ遅い。直接接続しているセグメントだったら、arp-scanだったりnmapだったり使えばすぐに取得できるのだが、その辺のコマンド入れてない(or入れられない)環境だったりした際に、コレをやるのはやはり面倒。手打ちしたらtypoする長さだし。

で、そもそも今の時代だったら帯域も1Gbpsで構成されている場合が多い(古くてもまぁ100MBpsはあるでしょと)わけで、例えば一気に/24で254個分のping打ったところで、大した影響は無いだろうと(環境によっては瞬間的とはいえ、プロセスが254個増えるのはちょっと問題あるかもだけど)。
とは言え、ちょっとは気にしてpingで送るパケットサイズは最小にしておいた上で、以下のようにコマンドを実行して一気にpingを実行してやる。

pingや見やすくするために使っているsortのオプションがLinuxとBSD(Mac OS X)で違うので、それぞれで分けて記述しておく。
ついでに、timeコマンドで処理時間も計測。

●Linuxの場合

echo 192.168.0.{1..254} | xargs -P254 -n1 ping -s1 -c1 -w1 | grep ttl | sort -V -k4
blacknon@BS-PUB-UBUNTU-01:~$ time (echo 192.168.0.{1..254} | xargs -P254 -n1 ping -s1 -c1 -w1 | grep ttl | sort -V -k4)
9 bytes from 192.168.0.1: icmp_seq=1 ttl=64
9 bytes from 192.168.0.12: icmp_seq=1 ttl=64
9 bytes from 192.168.0.14: icmp_seq=1 ttl=64
9 bytes from 192.168.0.20: icmp_seq=1 ttl=64
9 bytes from 192.168.0.42: icmp_seq=1 ttl=255
9 bytes from 192.168.0.43: icmp_seq=1 ttl=64
9 bytes from 192.168.0.53: icmp_seq=1 ttl=64
9 bytes from 192.168.0.102: icmp_seq=1 ttl=64
9 bytes from 192.168.0.104: icmp_seq=1 ttl=64
9 bytes from 192.168.0.106: icmp_seq=1 ttl=64
9 bytes from 192.168.0.107: icmp_seq=1 ttl=64
9 bytes from 192.168.0.117: icmp_seq=1 ttl=64
9 bytes from 192.168.0.118: icmp_seq=1 ttl=64
9 bytes from 192.168.0.119: icmp_seq=1 ttl=64
9 bytes from 192.168.0.120: icmp_seq=1 ttl=64
9 bytes from 192.168.0.121: icmp_seq=1 ttl=64
9 bytes from 192.168.0.132: icmp_seq=1 ttl=64
9 bytes from 192.168.0.133: icmp_seq=1 ttl=64
9 bytes from 192.168.0.134: icmp_seq=1 ttl=64
9 bytes from 192.168.0.169: icmp_seq=1 ttl=64
9 bytes from 192.168.0.170: icmp_seq=1 ttl=64
9 bytes from 192.168.0.171: icmp_seq=1 ttl=64
9 bytes from 192.168.0.176: icmp_seq=1 ttl=64
9 bytes from 192.168.0.187: icmp_seq=1 ttl=64
9 bytes from 192.168.0.194: icmp_seq=1 ttl=64
9 bytes from 192.168.0.195: icmp_seq=1 ttl=64
9 bytes from 192.168.0.196: icmp_seq=1 ttl=64
9 bytes from 192.168.0.197: icmp_seq=1 ttl=64
9 bytes from 192.168.0.198: icmp_seq=1 ttl=64
9 bytes from 192.168.0.199: icmp_seq=1 ttl=64
9 bytes from 192.168.0.201: icmp_seq=1 ttl=64
9 bytes from 192.168.0.203: icmp_seq=1 ttl=64
9 bytes from 192.168.0.204: icmp_seq=1 ttl=64
9 bytes from 192.168.0.205: icmp_seq=1 ttl=64
9 bytes from 192.168.0.230: icmp_seq=1 ttl=64

real    0m1.268s
user    0m0.008s
sys     0m0.072s

●Mac OS Xの場合

echo 192.168.0.{1..254} | xargs -P254 -n1 ping -s1 -c1 -W1 | grep ttl | gsort -V -k4 # gsort利用
echo 192.168.0.{1..254} | xargs -P254 -n1 ping -s1 -c1 -W1 | grep ttl | sort -t'.' -k1,1n -k2,2n -k3,3n -k4,4n
blacknon@BS-PUB-UBUNTU-01:~$ time (echo 192.168.0.{1..254} | xargs -P254 -n1 ping -s1 -c1 -w1 | grep ttl | sort -V -k4)
9 bytes from 192.168.0.1: icmp_seq=1 ttl=64
9 bytes from 192.168.0.12: icmp_seq=1 ttl=64
9 bytes from 192.168.0.14: icmp_seq=1 ttl=64
9 bytes from 192.168.0.20: icmp_seq=1 ttl=64
9 bytes from 192.168.0.42: icmp_seq=1 ttl=255
9 bytes from 192.168.0.43: icmp_seq=1 ttl=64
9 bytes from 192.168.0.53: icmp_seq=1 ttl=64
9 bytes from 192.168.0.102: icmp_seq=1 ttl=64
9 bytes from 192.168.0.104: icmp_seq=1 ttl=64
9 bytes from 192.168.0.106: icmp_seq=1 ttl=64
9 bytes from 192.168.0.107: icmp_seq=1 ttl=64
9 bytes from 192.168.0.117: icmp_seq=1 ttl=64
9 bytes from 192.168.0.118: icmp_seq=1 ttl=64
9 bytes from 192.168.0.119: icmp_seq=1 ttl=64
9 bytes from 192.168.0.120: icmp_seq=1 ttl=64
9 bytes from 192.168.0.121: icmp_seq=1 ttl=64
9 bytes from 192.168.0.132: icmp_seq=1 ttl=64
9 bytes from 192.168.0.133: icmp_seq=1 ttl=64
9 bytes from 192.168.0.134: icmp_seq=1 ttl=64
9 bytes from 192.168.0.169: icmp_seq=1 ttl=64
9 bytes from 192.168.0.170: icmp_seq=1 ttl=64
9 bytes from 192.168.0.171: icmp_seq=1 ttl=64
9 bytes from 192.168.0.176: icmp_seq=1 ttl=64
9 bytes from 192.168.0.187: icmp_seq=1 ttl=64
9 bytes from 192.168.0.194: icmp_seq=1 ttl=64
9 bytes from 192.168.0.195: icmp_seq=1 ttl=64
9 bytes from 192.168.0.196: icmp_seq=1 ttl=64
9 bytes from 192.168.0.197: icmp_seq=1 ttl=64
9 bytes from 192.168.0.198: icmp_seq=1 ttl=64
9 bytes from 192.168.0.199: icmp_seq=1 ttl=64
9 bytes from 192.168.0.201: icmp_seq=1 ttl=64
9 bytes from 192.168.0.203: icmp_seq=1 ttl=64
9 bytes from 192.168.0.204: icmp_seq=1 ttl=64
9 bytes from 192.168.0.205: icmp_seq=1 ttl=64
9 bytes from 192.168.0.230: icmp_seq=1 ttl=64

real    0m1.268s
user    0m0.008s
sys     0m0.072s
blacknon@BS-PUB-UBUNTU-01:~$ time (echo 192.168.0.{1..254} | xargs -P254 -n1 ping -s1 -c1 -W1 | grep ttl | sort -t'.' -k1,1n -k2,2n -k3,3n -k4,4n )
9 bytes from 192.168.0.1: icmp_seq=1 ttl=64
9 bytes from 192.168.0.12: icmp_seq=1 ttl=64
9 bytes from 192.168.0.14: icmp_seq=1 ttl=64
9 bytes from 192.168.0.20: icmp_seq=1 ttl=64
9 bytes from 192.168.0.42: icmp_seq=1 ttl=255
9 bytes from 192.168.0.43: icmp_seq=1 ttl=64
9 bytes from 192.168.0.53: icmp_seq=1 ttl=64
9 bytes from 192.168.0.102: icmp_seq=1 ttl=64
9 bytes from 192.168.0.104: icmp_seq=1 ttl=64
9 bytes from 192.168.0.106: icmp_seq=1 ttl=64
9 bytes from 192.168.0.107: icmp_seq=1 ttl=64
9 bytes from 192.168.0.117: icmp_seq=1 ttl=64
9 bytes from 192.168.0.118: icmp_seq=1 ttl=64
9 bytes from 192.168.0.119: icmp_seq=1 ttl=64
9 bytes from 192.168.0.120: icmp_seq=1 ttl=64
9 bytes from 192.168.0.121: icmp_seq=1 ttl=64
9 bytes from 192.168.0.132: icmp_seq=1 ttl=64
9 bytes from 192.168.0.133: icmp_seq=1 ttl=64
9 bytes from 192.168.0.134: icmp_seq=1 ttl=64
9 bytes from 192.168.0.169: icmp_seq=1 ttl=64
9 bytes from 192.168.0.170: icmp_seq=1 ttl=64
9 bytes from 192.168.0.171: icmp_seq=1 ttl=64
9 bytes from 192.168.0.176: icmp_seq=1 ttl=64
9 bytes from 192.168.0.187: icmp_seq=1 ttl=64
9 bytes from 192.168.0.194: icmp_seq=1 ttl=64
9 bytes from 192.168.0.195: icmp_seq=1 ttl=64
9 bytes from 192.168.0.196: icmp_seq=1 ttl=64
9 bytes from 192.168.0.197: icmp_seq=1 ttl=64
9 bytes from 192.168.0.198: icmp_seq=1 ttl=64
9 bytes from 192.168.0.199: icmp_seq=1 ttl=64
9 bytes from 192.168.0.201: icmp_seq=1 ttl=64
9 bytes from 192.168.0.203: icmp_seq=1 ttl=64
9 bytes from 192.168.0.204: icmp_seq=1 ttl=64
9 bytes from 192.168.0.205: icmp_seq=1 ttl=64
9 bytes from 192.168.0.230: icmp_seq=1 ttl=64

real    0m1.244s
user    0m0.000s
sys     0m0.076s

 

計測結果を見るとわかるように、1秒ほどで254台に対して疎通確認を行うことができた。
ちなみに、このやり方だとTTLも確認ができるので、対象のIPアドレスのOSが何を使ってるのかについても大体推測ができる(64だとLinux、124だとWindows、256だとUNIX系と推測できる)。

 

~番外編~

MacやLinuxはこれで良いとして、Windowsではどうすればいいか。
とりあえず、Windows 10であればBash on Windowsの機能を利用すれば同じことができるだろう(中身Ubuntuだし)。もしくは、PowerShell 3以降が入っているようなら、以下のようにコマンドを実行することで(ちょっと遅い+長いけど)pingをパラレルに実行できそうだ。
PowerShellでパラレルでのコマンド実行を行う場合、どうもwordkflowとして定義が必要になるらしいので、このような形になった。もっと良い書き方ありそうなもんだけど…

workflow x{foreach -parallel($a in 1..254) {ping -l 1 -n 1 -w 10 172.20.100.$a}};x

 

ちょっとだけLinuxにさわってみたい人のための Bash on Ubuntu on Windows入門 ちょっとだけLinuxにさわってみたい人のための Bash on Ubuntu on Windows入門

コンソールで文字列の各文字をシャッフルさせる

$
0
0

コンソール上で適当な文字列をシャッフルさせて出力させる場合だと、以下のようにshufコマンドを利用する方法が楽だと思う。
以下、実行例。

echo $(echo 山田エルフ|grep -o .|shuf|tr -d '\n')
echo $(echo 山田エルフ|fold -w1|sort -R|tr -d '\n')

[root@BS-PUB-CENT7-01 ~]# echo $(echo 山田エルフ|grep -o .|shuf|tr -d '\n')
田エフ山ル
[root@BS-PUB-CENT7-01 ~]# echo $(echo 山田エルフ|fold -w1|sort -R|tr -d '\n')
ル田フ山エ

 

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

 

 

 

 

 

 

 

秘密鍵ファイルからssh接続用の公開鍵を再度生成する

$
0
0

sshで公開鍵認証を使っている際、手元に秘密鍵はあるのだけど、間違えて公開鍵を削除してしまったり、なくしてしまった場合というのがある。
そんなときは、秘密鍵さえあるのなら以下のコマンドで公開鍵を出力できる。

ssh-keygen -y 秘密鍵のPATH
[root@BS-PUB-CENT7-01 ~]# cat testkey.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDVntFu0YdUXBerSVVKwX495TKxFuUV7y6yo+Ybx2oYAyZzPVAuXgoWctqwbbM7XmhAwidQtqjCy4xLUAZSTlXvzud2XWfszt190Rb6kqEbLWkycuiOpNmo7nRkKuMac0ickyMS4eJ/D4MfzTzyfd0T4d7NeRGS5o0T3br4xk3YMvULHnqe6VDr8MZvtsH4JgeXbcUPXAGU9QaHbuODGpJO3N+BJEo8b3dEMBkpV+zOcXSve9BUDGEj5gdra6nj0CUzE08PFsECiqGIUaB2ZLUgUoU9qy/CJZUxs2nW9V+QRzsuNHOyV0UtXtNmkshvz/ARdj/vleGUJKOUm9y2JaYH root@BS-PUB-CENT7-01.blacknon.local
[root@BS-PUB-CENT7-01 ~]#
[root@BS-PUB-CENT7-01 ~]# ssh-keygen -y -f testkey
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDVntFu0YdUXBerSVVKwX495TKxFuUV7y6yo+Ybx2oYAyZzPVAuXgoWctqwbbM7XmhAwidQtqjCy4xLUAZSTlXvzud2XWfszt190Rb6kqEbLWkycuiOpNmo7nRkKuMac0ickyMS4eJ/D4MfzTzyfd0T4d7NeRGS5o0T3br4xk3YMvULHnqe6VDr8MZvtsH4JgeXbcUPXAGU9QaHbuODGpJO3N+BJEo8b3dEMBkpV+zOcXSve9BUDGEj5gdra6nj0CUzE08PFsECiqGIUaB2ZLUgUoU9qy/CJZUxs2nW9V+QRzsuNHOyV0UtXtNmkshvz/ARdj/vleGUJKOUm9y2JaYH
[root@BS-PUB-CENT7-01 ~]#
[root@BS-PUB-CENT7-01 ~]# diff <(ssh-keygen -y -f testkey) <(cat testkey.pub | awk '{print $1,$2}')
[root@BS-PUB-CENT7-01 ~]#

出力される公開鍵ファイル自体は同じものなので、後はそれをそのまま利用すれば良い。
…で、問題はその逆。公開鍵ファイルはあるのだが、それに対応する秘密鍵ファイルがどれだかわからないパターン。1個1個使ってssh接続できるかどうかを確認するのもいいが、それをやりたくないのであれば、以下のように秘密鍵ファイルから公開鍵ファイルを生成して、手元にある対象サーバの公開鍵ファイルとマッチするかどうか確認すればいい。

find PATH -type f -exec file {} \; | awk -F':' '$2 ~ /private key/{print $1}' | xargs -I@ bash -c 'printf "@: ";ssh-keygen -y -f "@"' | grep -e $ -e 公開鍵の一部

 

なお、先日上記作業が必要になって一生懸命秘密鍵を探したのだが、なんか自分のPCの中にはなかった…(´・ω・`)。
非常に困った。どうしようかなぁ…。

 

OpenSSH[実践]入門 (Software Design plus) OpenSSH[実践]入門 (Software Design plus)

utmpdumpを使って/var/log/wtmp(lastコマンド)、/var/log/btmp(lastbコマンド)のログを編集して改ざんする

$
0
0

夜中に寝れなくなって、なんとなくlastコマンド、lastbコマンドのログ改ざんできないんかなと思っていじってたところ、root権限があれば、utmpdumpで一度テキストに変換してから再度バイナリファイルに変換することで簡単に改ざんできてしまったので、備忘として残しておく。

utmpdumpコマンド自体はCentOS 7やUbuntu Server 16.04 LTSであれば最初からインストールされているはずなので、まずは以下のコマンドでwtmp、btmpをバイナリからテキストにエクスポートする。

utmpdump /var/log/wtmp > ~/wtmp.txt
[root@BS-PUB-WEBTOOL-TEST01 ~]# utmpdump /var/log/wtmp
Utmp dump of /var/log/wtmp/
[2] [00000] [~~  ] [reboot  ] [~           ] [3.10.0-327.el7.x86_64] [0.0.0.0        ] [土  2月 20 23:03:43 2016  ]
[5] [00635] [tty1] [        ] [tty1        ] [                    ] [0.0.0.0        ] [土  2月 20 23:03:57 2016  ]
[6] [00635] [tty1] [LOGIN   ] [tty1        ] [                    ] [0.0.0.0        ] [土  2月 20 23:03:57 2016  ]
[1] [00051] [~~  ] [runlevel] [~           ] [3.10.0-327.el7.x86_64] [0.0.0.0        ] [土  2月 20 23:04:03 2016  ]
[7] [00635] [tty1] [root    ] [tty1        ] [                    ] [0.0.0.0        ] [日  2月 21 13:26:41 2016  ]
[8] [00635] [tty1] [        ] [tty1        ] [                    ] [0.0.0.0        ] [日  2月 21 13:27:22 2016  ]
…
[root@BS-PUB-WEBTOOL-TEST01 ~]# utmpdump /var/log/wtmp > ~/wtmp.txt
Utmp dump of /var/log/wtmp

テキストにエクスポートしたwtmpログを改ざん(とりあえず、今回は直近のログをざっくり削除)したら、以下のコマンドでwtmpログを改ざんした内容に置き換える。

utmpdump --reverse ~/wtmp.txt > /var/log/wtmp
[root@BS-PUB-WEBTOOL-TEST01 ~]# last | head -10
root     pts/2        192.168.10.210    Mon Jun  5 00:08   still logged in
root     pts/1        192.168.10.210    Sun Jun  4 17:26   still logged in
root     pts/0        192.168.10.210    Sat May 20 15:55   still logged in
root     pts/1        172.20.100.118   Sat Apr  8 22:50 - 23:03  (00:12)
root     pts/1        172.20.100.118   Sat Apr  8 21:33 - 21:35  (00:01)
root     pts/0        192.168.10.210    Sat Apr  8 21:21 - 23:15  (01:54)
root     pts/0        192.168.10.210    Tue Mar 14 22:21 - 22:21  (00:00)
reboot   system boot  3.10.0-514.10.2. Sat Mar  4 19:02 - 06:06 (93+11:03)
root     pts/1        192.168.10.210    Mon Oct 31 08:05 - down   (00:37)
root     pts/0        192.168.10.210    Mon Oct 31 07:51 - down   (00:50)
[root@BS-PUB-WEBTOOL-TEST01 ~]# utmpdump --reverse ~/wtmp.txt > /var/log/wtmp
Utmp undump of /root/wtmp.txt
[root@BS-PUB-WEBTOOL-TEST01 ~]# last | head -10
root     pts/0        192.168.10.210    Tue Mar 14 22:21 - 22:21  (00:00)
reboot   system boot  3.10.0-514.10.2. Sat Mar  4 19:02 - 06:06 (93+11:03)
root     pts/1        192.168.10.210    Mon Oct 31 08:05 - down   (00:37)
root     pts/0        192.168.10.210    Mon Oct 31 07:51 - down   (00:50)
reboot   system boot  3.10.0-327.el7.x Mon Oct 31 07:50 - 08:42  (00:52)
root     tty1                          Sat Jul 30 11:38 - 11:39  (00:01)
reboot   system boot  3.10.0-327.el7.x Sat Jul 30 11:34 - 08:42 (92+21:08)
root     tty1                          Sun Feb 28 22:36 - 22:38  (00:01)
reboot   system boot  3.10.0-327.el7.x Sun Feb 28 20:33 - 14:34 (63+18:00)
root     pts/1        192.168.10.150    Sun Feb 21 13:35 - 13:35  (00:00)

 

想定どおり、lastコマンドで閲覧できる内容が改ざんできた。
lastbコマンド(ログインの失敗履歴)についても同様のことができる。改ざんには基本的にroot権限が必要なので、まぁあまり気にする必要も無いかなと思うけど、確認時はlastコマンドだけじゃなくてlastlogとでも確認するとか、/var/log/secureをちゃんとsyslogサーバに飛ばして監視するとか、SELinuxやら拡張属性の設定するとか、何かしらの対応をしたほうが良いよねと思った。

(そもそも、書き込み権限さえあれば以下のようにログの中身を空にできるので…)

[root@BS-PUB-WEBTOOL-TEST01 ~]# echo '' > /var/log/wtmp
[root@BS-PUB-WEBTOOL-TEST01 ~]# last

wtmp begins Tue Jun  6 06:13:01 2017
[root@BS-PUB-WEBTOOL-TEST01 ~]# echo '' > /var/log/btmp
[root@BS-PUB-WEBTOOL-TEST01 ~]# lastb

btmp begins Tue Jun  6 06:21:45 2017
[root@BS-PUB-WEBTOOL-TEST01 ~]# echo '' > /var/log/lastlog
[root@BS-PUB-WEBTOOL-TEST01 ~]# lastlog
ユーザ名         ポート   場所             最近のログイン
root                                       **一度もログインしていません**
bin                                        **一度もログインしていません**
daemon                                     **一度もログインしていません**
adm                                        **一度もログインしていません**
lp                                         **一度もログインしていません**
sync                                       **一度もログインしていません**
shutdown                                   **一度もログインしていません**
halt                                       **一度もログインしていません**
mail                                       **一度もログインしていません**
operator                                   **一度もログインしていません**
games                                      **一度もログインしていません**
ftp                                        **一度もログインしていません**
nobody                                     **一度もログインしていません**
avahi-autoipd                              **一度もログインしていません**
systemd-bus-proxy                           **一度もログインしていません**
systemd-network                            **一度もログインしていません**
dbus                                       **一度もログインしていません**
polkitd                                    **一度もログインしていません**
tss                                        **一度もログインしていません**
postfix                                    **一度もログインしていません**
sshd                                       **一度もログインしていません**

 

よくわかるシステム監査の実務解説(改訂版) よくわかるシステム監査の実務解説(改訂版)

bashでファイルを処理して結果をそのファイルに上書きする

$
0
0

bashでファイルを利用して処理を行い、その結果を処理に使ったファイルに上書き・追記するといった場合、普通にやると対象のファイルが空になってしまう。

[root@BS-PUB-CENT7-01 ~]# cat -n test.txt
     1  a01 a02 a03 a04 a05 a06 a07 a08 a09 a10
     2  b01 b02 b03 b04 b05 b06 b07 b08 b09 b10
     3  c01 c02 c03 c04 c05 c06 c07 c08 c09 c10
     4  d01 d02 d03 d04 d05 d06 d07 d08 d09 d10
     5  e01 e02 e03 e04 e05 e06 e07 e08 e09 e10
     6  f01 f02 f03 f04 f05 f06 f07 f08 f09 f10
     7  g01 g02 g03 g04 g05 g06 g07 g08 g09 g10
     8  h01 h02 h03 h04 h05 h06 h07 h08 h09 h10
     9  i01 i02 i03 i04 i05 i06 i07 i08 i09 i10
    10  j01 j02 j03 j04 j05 j06 j07 j08 j09 j10
[root@BS-PUB-CENT7-01 ~]# cat -n test.txt | head -1 > ./test.txt
[root@BS-PUB-CENT7-01 ~]# cat ./test.txt
[root@BS-PUB-CENT7-01 ~]#

 

これは、上書きだった場合にはリダイレクト実行時に空ファイルが自動的に作られ、そこに実行結果を記述するといった動きをするかららしい。
そのためか、追記は普通にできたりする(grepなど、一部のコマンドはチェック処理が走るためダメ)。

[root@BS-PUB-CENT7-01 ~]# cat -n test.txt
     1  a01 a02 a03 a04 a05 a06 a07 a08 a09 a10
     2  b01 b02 b03 b04 b05 b06 b07 b08 b09 b10
     3  c01 c02 c03 c04 c05 c06 c07 c08 c09 c10
     4  d01 d02 d03 d04 d05 d06 d07 d08 d09 d10
     5  e01 e02 e03 e04 e05 e06 e07 e08 e09 e10
     6  f01 f02 f03 f04 f05 f06 f07 f08 f09 f10
     7  g01 g02 g03 g04 g05 g06 g07 g08 g09 g10
     8  h01 h02 h03 h04 h05 h06 h07 h08 h09 h10
     9  i01 i02 i03 i04 i05 i06 i07 i08 i09 i10
    10  j01 j02 j03 j04 j05 j06 j07 j08 j09 j10
[root@BS-PUB-CENT7-01 ~]# cat -n test.txt | head -1 >> ./test.txt
[root@BS-PUB-CENT7-01 ~]# cat test.txt
a01 a02 a03 a04 a05 a06 a07 a08 a09 a10
b01 b02 b03 b04 b05 b06 b07 b08 b09 b10
c01 c02 c03 c04 c05 c06 c07 c08 c09 c10
d01 d02 d03 d04 d05 d06 d07 d08 d09 d10
e01 e02 e03 e04 e05 e06 e07 e08 e09 e10
f01 f02 f03 f04 f05 f06 f07 f08 f09 f10
g01 g02 g03 g04 g05 g06 g07 g08 g09 g10
h01 h02 h03 h04 h05 h06 h07 h08 h09 h10
i01 i02 i03 i04 i05 i06 i07 i08 i09 i10
j01 j02 j03 j04 j05 j06 j07 j08 j09 j10
     1  a01 a02 a03 a04 a05 a06 a07 a08 a09 a10

 

では、処理結果をどのように上書きすればよいか。一時ファイルなんて作りたくはない…。しかし、テストしたがファイルディスクリプタを使ってもうまくはいかないので、どうすればいいか。
色々と調べてみたところ、以下の2通りのやり方がありそうだ。

1.プロセス置換を利用する

プロセス置換を利用して、以下のようにコマンドを実行することで上書き処理が行えた。
なお、この際sleepコマンドが無いと、リダイレクトが行われる処理のタイミングによってはそのままからファイルになってしまうことがあるので注意。

コマンド File.path > >( sleep 1 && cat > File.path)
[root@BS-PUB-CENT7-01 ~]# cat test.txt
a01 a02 a03 a04 a05 a06 a07 a08 a09 a10
b01 b02 b03 b04 b05 b06 b07 b08 b09 b10
c01 c02 c03 c04 c05 c06 c07 c08 c09 c10
d01 d02 d03 d04 d05 d06 d07 d08 d09 d10
e01 e02 e03 e04 e05 e06 e07 e08 e09 e10
f01 f02 f03 f04 f05 f06 f07 f08 f09 f10
g01 g02 g03 g04 g05 g06 g07 g08 g09 g10
h01 h02 h03 h04 h05 h06 h07 h08 h09 h10
i01 i02 i03 i04 i05 i06 i07 i08 i09 i10
j01 j02 j03 j04 j05 j06 j07 j08 j09 j10
[root@BS-PUB-CENT7-01 ~]# head -1 test.txt
a01 a02 a03 a04 a05 a06 a07 a08 a09 a10
[root@BS-PUB-CENT7-01 ~]# head -1 test.txt > >(sleep 1 && cat > test.txt)
[root@BS-PUB-CENT7-01 ~]# cat test.txt
a01 a02 a03 a04 a05 a06 a07 a08 a09 a10
[root@BS-PUB-CENT7-01 ~]#

2.moreutilsのspongeコマンドを用いる

上記のプロセス置換を利用する方法のほか、moreutilsにあるspongeコマンドを用いることで、そのままファイルを上書きできる。

コマンド File.path | sponge File.path
[root@BS-PUB-CENT7-01 ~]# cat test.txt
a01 a02 a03 a04 a05 a06 a07 a08 a09 a10
b01 b02 b03 b04 b05 b06 b07 b08 b09 b10
c01 c02 c03 c04 c05 c06 c07 c08 c09 c10
d01 d02 d03 d04 d05 d06 d07 d08 d09 d10
e01 e02 e03 e04 e05 e06 e07 e08 e09 e10
f01 f02 f03 f04 f05 f06 f07 f08 f09 f10
g01 g02 g03 g04 g05 g06 g07 g08 g09 g10
h01 h02 h03 h04 h05 h06 h07 h08 h09 h10
i01 i02 i03 i04 i05 i06 i07 i08 i09 i10
j01 j02 j03 j04 j05 j06 j07 j08 j09 j10
[root@BS-PUB-CENT7-01 ~]# head -2 test.txt
a01 a02 a03 a04 a05 a06 a07 a08 a09 a10
b01 b02 b03 b04 b05 b06 b07 b08 b09 b10
[root@BS-PUB-CENT7-01 ~]# head -2 test.txt | sponge test.txt
[root@BS-PUB-CENT7-01 ~]# cat test.txt
a01 a02 a03 a04 a05 a06 a07 a08 a09 a10
b01 b02 b03 b04 b05 b06 b07 b08 b09 b10

 

sedなど、上書きオプションの無いコマンドの結果を上書きしたい場合、このような方法で(半ば無理やり感はあるけど)上書きは可能なようだ。

シェルプログラミング実用テクニック シェルプログラミング実用テクニック

CentOS 7にオープンソースのSSOサーバ『Keycloak』を触ってみる

$
0
0

ちょっとした好奇心というか、マイブーム的なものでWebアプリケーションのSSO(シングルサインオン)ツールについて調べていたところ、RedHatの出しているツール『Keycloak』が良さそうだというのを見かけたので、CentOS 7で触ってみることにした。ただ、SSOだとログイン先の設定なども必要になってきて色々と準備も必要になるので、数回に分けることにして、今回は管理画面を表示するまでにしておく。なお、バージョンは3.1.0を用い、.serviceファイルは今回は作成しない(次回以降)。あと、(本当は良くないのだが、今回はお試しなので…)FirewalldとSELinuxは無効にしている。

1.事前準備

まず、動作用のユーザの作成と、ダウンロードに必要になるパッケージを導入する。

useradd keycloak
yum install -y git wget

 

動作にMavenが必要になるので、それらをインストールする。
まずはOracle JDKのインストールを行う。

wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.rpm
rpm -ihv jdk-8u131-linux-x64.rpm

 

次に、Mavenのインストール。
作業中に実行ユーザに切り替えて、PATHを通しておく。

cd /opt
wget http://ftp.riken.jp/net/apache/maven/maven-3/3.5.0/binaries/apache-maven-3.5.0-bin.tar.gz
tar xzvf apache-maven-3.5.0-bin.tar.gz
mv apache-maven{-3.5.0,}
su - keycloak
cat << "EOF" >> ~/.bash_profile
export JAVA_HOME=/usr/java/default/
export PATH=$PATH:/opt/apache-maven/bin
EOF
. ~/.bash_profile

2.KeycloakをStandaloneで動作させてみる

諸々の準備ができたら、以下のコマンドでKeycloakのソースをダウンロードして、動作させてみよう。スクリプトで動作させる場合、どうもコンテナで動いてるようだ。
そのまま起動させると127.0.0.1でしかアクセスできなくなるので、事前に設定ファイルを操作してサーバのIPアドレスを指定する。

wget https://downloads.jboss.org/keycloak/3.1.0.Final/keycloak-3.1.0.Final.tar.gz
tar xzvf keycloak-*.tar.gz
mv keycloak-*/ keycloak
cd keycloak
sed -i.bk '{s/127.0.0.1/IPアドレス/g}' standalone/configuration/standalone.xml
bin/add-user-keycloak.sh -u admin -p パスワード
bin/standalone.sh -b 0.0.0.0

 

プログラム実行後、「http://サーバのIPアドレス:8080/auth/admin」にブラウザからアクセスすると、以下の画面が表示されるので、先程作成したユーザ(admin)でログインする。
(とりあえずプログラムを動かしてるだけなので、オレオレ証明書でのSSL化もされていない状態)

 

ログイン後の画面はこんな感じ。

 

ひと目でわかるActive Directory Windows Server 2016版 ひと目でわかるActive Directory Windows Server 2016版

 

awkで処理結果を元になったファイルに上書きする

$
0
0

ふと、「awkでファイルの上書き保存ってどうすんだろうなぁ…。GNU sedだったら-iオプションで上書きできるけど、awkだとんなオプションなかったよなぁ…」と思ってちょっと調べてみたところ、どうやらGNU awkの場合だと4.1.0以降で上書きができるようになってたらしい。知らなかった…。
以下のように、-i inplaceで指定することで上書きができるようだ(参考:The GNU Awk User’s Guide: Extension Sample Inplace)。

awk -i inplace '{ ... }' File.path

blacknon@BS-PUB-DEVELOP:~$ awk --version | head -1
GNU Awk 4.1.3, API: 1.1 (GNU MPFR 3.1.4, GNU MP 6.1.0)
blacknon@BS-PUB-DEVELOP:~$
blacknon@BS-PUB-DEVELOP:~$ cat awk_test.txt
A_01 A_02 A_03 A_04 A_05
B_01 B_02 B_03 B_04 B_05
C_01 C_02 C_03 C_04 C_05
D_01 D_02 D_03 D_04 D_05
E_01 E_02 E_03 E_04 E_05
F_01 F_02 F_03 F_04 F_05
G_01 G_02 G_03 G_04 G_05
H_01 H_02 H_03 H_04 H_05
blacknon@BS-PUB-DEVELOP:~$
blacknon@BS-PUB-DEVELOP:~$ awk 'NR>4{print $1}' awk_test.txt
E_01
F_01
G_01
H_01
blacknon@BS-PUB-DEVELOP:~$
blacknon@BS-PUB-DEVELOP:~$ awk -i inplace 'NR>4{print $1}' awk_test.txt
blacknon@BS-PUB-DEVELOP:~$
blacknon@BS-PUB-DEVELOP:~$ cat awk_test.txt
E_01
F_01
G_01
H_01

知らなかった…。こんな便利な機能があったとは…。
ただ、残念ながらCentOS 7などでは、デフォルトで用意されているawkのバージョンがちょっと古く(手元の環境だと4.0.2とか)、この機能は使えなそう。とりあえず、サブシェルでうまいことやれば上書き自体はできるけど…。正直、毎回書きたくないなぁ…。

awk '{ ... }' file.path > >(sleep 1 && cat > file.path)
[root@BS-PUB-CENT7-01 ~]# cat test.txt
a01 a02 a03 a04 a05 a06 a07 a08 a09 a10
b01 b02 b03 b04 b05 b06 b07 b08 b09 b10
[root@BS-PUB-CENT7-01 ~]# awk '{print $1}' test.txt
a01
b01
[root@BS-PUB-CENT7-01 ~]# awk '{print $1}' test.txt > >(sleep 1 && cat > test.txt)
[root@BS-PUB-CENT7-01 ~]# cat test.txt
a01
b01
[root@BS-PUB-CENT7-01 ~]# awk --version | head -1
GNU Awk 4.0.2

 

「シェル芸」に効く!AWK処方箋 「シェル芸」に効く!AWK処方箋

Microsoft Azure上のLinuxサーバで秘密鍵をなくしてしまった場合

$
0
0

Microsoft Azure上で鍵認証でLinuxを使っているのだが、諸事情によりログイン用の秘密鍵を紛失してしまうといったことがあった。
流石に何処かにはあるだろうと色々と探したのだけど、どうしても見つからない。どうすりゃいいかなぁ…と調べていたところ、Azureポータルの対象VMを選択すると「パスワードのリセット」なる項目が。藁にもすがる思いでそこから公開鍵を登録してみることにした。

で、ここから公開鍵登録をしてみたところ、対象のユーザの「.ssh/authorized_keys」に対象の公開鍵が追記され、再起動や旧公開鍵の削除といったことも行われなかった。
おお…、つまり、AzureのVMで秘密鍵をなくした場合(そもそも無くすなって話なんだけど)は、そこらじゅう探すよりもとっとと登録してしまった方が早いということね。Azure上にあったVMイメージから作ったものだから、管理用のエージェントからこういった対応ができるようだ。

ちょっと無駄な時間の使い方をしてた。もし同じような人がいた場合は、鍵ファイルの利用状況の調査だけしてとっとと公開鍵追加したほうが良いと思う。

 

Azureテクノロジ入門2016 (マイクロソフト関連書) Azureテクノロジ入門2016 (マイクロソフト関連書)

 

grepで日付・タイムスタンプを抽出する

$
0
0

ちょっとした作業で、日付やタイムスタンプを取得する必要があったので、一応念の為残しておく。

grep -E '20[0-9]{2}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}'
grep -P '\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}'

 

これで、「YYYY/mm/dd HH:MM:SS」相当の文字列をgrepできる(厳密には違うけど)。

詳説 正規表現 第3版 詳説 正規表現 第3版

bashでゼロ埋め・スペース埋め(パディング)をする

$
0
0

bashで出力する数字や文字列のゼロ埋め・スペース埋めをする場合、printfを用いて以下のようにすると良いだろう。

printf "'%07d'\n" 1234 # ゼロ埋め
printf "'%7d'\n" 1234  # スペース埋め
printf "'%-7d'\n" 1234 # スペース埋め(左寄り)

blacknon@BS-PUB-DEVELOP:~$ printf "'%07d'\n" 1234
'0001234'
blacknon@BS-PUB-DEVELOP:~$ printf "'%7d'\n" 1234
'   1234'
blacknon@BS-PUB-DEVELOP:~$ printf "'%-7d'\n" 1234
'1234   '

 

ちょっとだけLinuxにさわってみたい人のための Bash on Ubuntu on Windows入門 ちょっとだけLinuxにさわってみたい人のための Bash on Ubuntu on Windows入門

読み取りにroot権限が必要なリモートサーバのファイルをssh経由でローカルにコピーする(sudoが使えること前提)

$
0
0

時折、リモートサーバにある”ログインユーザでは読み取りができないファイル”をそのままローカルにコピーしたいことがある。ssh経由でファイルをコピーするといえばscpがよく使われる方法だと思うが、残念ながらscpではリモートサーバ側でsudoを使ってroot権限でファイルを読み込んだりといった事はできない。さて、じゃどうすればいいのだろうか。
こういったとき、sudoをNOPASSWDで実行可能な状態であれば、単体のファイルであればsshコマンドからsudoを使ってcatで、ディレクトリごとであれば一度tarでアーカイブ化してローカルでそのまま展開させる事ができる。なお、RHEL系のデフォルトではsudo実行には擬似端末が必要になる(AWSやAzureのCentOSイメージでは手が加えてある様子)のだが、catコマンドはsshコマンド実行時に-ttの付与しておけば良いのだが、tarに関しては擬似端末を利用してのssh越しの実行ができない。このため、/etc/sudoersにてrequirettyを無効化しておく必要があるので注意。

ssh -t user@host 'sudo cat RemoteFile.path' > LocalFile.path # 単体ファイルの場合
ssh user@host 'sudo tar -C RemoteSourceDir czf - .' | tar -C LocalDestinationDir -xzf - # ディレクトリの場合
blacknon@BS-PUB-DEVELOP:~$ ssh -t test@BS-PUB-CENT7-01 'cat /var/log/secure'
cat: /var/log/secure: 許可がありません
Connection to bs-pub-cent7-01 closed.
blacknon@BS-PUB-DEVELOP:~$ ssh -t test@BS-PUB-CENT7-01 'sudo cat /var/log/secure' > ./secure
Connection to bs-pub-cent7-01 closed.
blacknon@BS-PUB-DEVELOP:~$ tail secure
Jun 12 11:30:58 BS-PUB-CENT7-01 sudo: pam_unix(sudo:auth): auth could not identify password for [test]
Jun 12 11:30:58 BS-PUB-CENT7-01 sshd[21013]: Received disconnect from 172.28.0.171: 11: disconnected by user
Jun 12 11:30:58 BS-PUB-CENT7-01 sshd[21010]: pam_unix(sshd:session): session closed for user test
Jun 12 11:31:01 BS-PUB-CENT7-01 sshd[21118]: Accepted publickey for test from 172.28.0.171 port 46934 ssh2: RSA 81:0c:f5:73:11:2e:e7:d7:8d:4c:fd:b5:cc:3d:40:f5
Jun 12 11:31:03 BS-PUB-CENT7-01 sshd[21118]: pam_unix(sshd:session): session opened for user test by (uid=0)
Jun 12 11:31:04 BS-PUB-CENT7-01 sshd[21121]: Received disconnect from 172.28.0.171: 11: disconnected by user
Jun 12 11:31:04 BS-PUB-CENT7-01 sshd[21118]: pam_unix(sshd:session): session closed for user test
Jun 12 11:31:06 BS-PUB-CENT7-01 sshd[21138]: Accepted publickey for test from 172.28.0.171 port 46936 ssh2: RSA 81:0c:f5:73:11:2e:e7:d7:8d:4c:fd:b5:cc:3d:40:f5
Jun 12 11:31:08 BS-PUB-CENT7-01 sshd[21138]: pam_unix(sshd:session): session opened for user test by (uid=0)
Jun 12 11:31:09 BS-PUB-CENT7-01 sudo:    test : TTY=pts/2 ; PWD=/home/test ; USER=root ; COMMAND=/bin/cat /var/log/secure
blacknon@BS-PUB-DEVELOP:~$ ssh  test@BS-PUB-CENT7-01 'sudo tar -C /var/log -czf - .' | tar -C ./testLogDir/ -xzf -
blacknon@BS-PUB-DEVELOP:~$ ls testLogDir/
anaconda       cron-20170604       lastlog            messages-20170529  secure-20170604   tuned
audit          cron-20170612       maillog            messages-20170604  secure-20170612   wpa_supplicant.log
boot.log       dmesg               maillog-20160306   messages-20170612  spooler           wtmp
btmp           dmesg.old           maillog-20170529   nginx              spooler-20160306  wtmp.bk
btmp-20170601  firewalld           maillog-20170604   ppp                spooler-20170529  yum.log
cron           grubby              maillog-20170612   secure             spooler-20170604
cron-20160306  grubby_prune_debug  messages           secure-20160306    spooler-20170612
cron-20170529  httpd               messages-20160306  secure-20170529    tallylog

なお、この時sudo実行時にパスワードが必要な場合、以下のように標準入力から受付けさせるようにする。なお、この際標準エラー出力を/dev/nullに吐かせないと、sudoのパスワード入力プロンプトがリダイレクト先に出力されてしまうので注意。
(サンプルでは、量が多くなるのでtailで取得している)

ssh -t user@host 'echo Password |sudo -S cat RemoteFile.path 2>/dev/null' > LocalFile.path # パイプで渡す場合
ssh -t user@host 'sudo -S cat RemoteFile.path 2>/dev/null' > LocalFile.path # プロンプト等出ないが、そのままパスワードを入力
ssh user@host 'echo Password | sudo -S tar -C RemoteSourceDir -czf - . 2>/dev/null' | tar -C LocalDestinationDir -xzf - # パスワードをパイプで渡してディレクトリごと取得する場合
blacknon@BS-PUB-DEVELOP:~$ ssh -t blacknon@BS-PUB-UBUNTU-01.blacknon.local 'sudo -S tail -5 /var/log/syslog 2>/dev/null' > tail_test3.log
blacknon@bs-pub-ubuntu-01.blacknon.local's password:
Connection to bs-pub-ubuntu-01.blacknon.local closed.
blacknon@BS-PUB-DEVELOP:~$ cat tail_test3.log
Jun 13 00:07:50 BS-PUB-UBUNTU-01 systemd[1]: Started Session 3347 of user blacknon.
Jun 13 00:08:10 BS-PUB-UBUNTU-01 systemd[1]: Started Session 3348 of user blacknon.
Jun 13 00:08:33 BS-PUB-UBUNTU-01 systemd[1]: Started Session 3349 of user blacknon.
Jun 13 00:10:13 BS-PUB-UBUNTU-01 systemd[1]: Started Session 3350 of user blacknon.
Jun 13 00:10:27 BS-PUB-UBUNTU-01 systemd[1]: Started Session 3351 of user blacknon.
blacknon@BS-PUB-DEVELOP:~$
blacknon@BS-PUB-DEVELOP:~$ ssh -t blacknon@BS-PUB-UBUNTU-01.blacknon.local 'echo Password | sudo -S tail -5 /var/log/syslog 2>/dev/null' > tail_test3.log
blacknon@bs-pub-ubuntu-01.blacknon.local's password:
Connection to bs-pub-ubuntu-01.blacknon.local closed.
blacknon@BS-PUB-DEVELOP:~$ cat tail_test3.log
Jun 13 00:10:48 BS-PUB-UBUNTU-01 sm-mta[29803]: v57LUkgo005932: to=<root@BS-PUB-UBUNTU-01.BLACKNON.LOCAL>, delay=4+17:40:01, xdelay=00:00:00, mailer=local, pri=61410000, dsn=4.0.0, stat=Operating system error
Jun 13 00:10:48 BS-PUB-UBUNTU-01 sm-mta[29825]: v57LP2gm005928: Warning: program /usr/sbin/sensible-mda unsafe: No such file or directory
Jun 13 00:10:48 BS-PUB-UBUNTU-01 sm-mta[29825]: v57LP2gm005928: SYSERR(root): Cannot exec /usr/sbin/sensible-mda: No such file or directory
Jun 13 00:10:48 BS-PUB-UBUNTU-01 sm-mta[29803]: v57LP2gm005928: to=<root@BS-PUB-UBUNTU-01.BLACKNON.LOCAL>, ctladdr=<root@BS-PUB-UBUNTU-01.BLACKNON.LOCAL> (0/0), delay=4+17:45:46, xdelay=00:00:00, mailer=local, pri=61501361, dsn=4.0.0, stat=Operating system error
Jun 13 00:10:52 BS-PUB-UBUNTU-01 systemd[1]: Started Session 3352 of user blacknon.
blacknon@BS-PUB-DEVELOP:~$ ssh -i testkey blacknon@BS-PUB-UBUNTU-01.blacknon.local 'echo Password | sudo -S tar -C /var/log -czf - . 2>/dev/null' | tar -C ./testLogDir2 -xzf -
blacknon@BS-PUB-DEVELOP:~$ ls -a testLogDir2
.                      auth.log       dmesg.1.gz     faillog         mail.err.1     syslog.1
..                     auth.log.1     dmesg.2.gz     fontconfig.log  mail.err.2.gz  syslog.2.gz
alternatives.log       auth.log.2.gz  dmesg.3.gz     fsck            mail.err.3.gz  syslog.3.gz
alternatives.log.1     auth.log.3.gz  dmesg.4.gz     installer       mail.err.4.gz  syslog.4.gz
alternatives.log.2.gz  auth.log.4.gz  dpkg.log       kern.log        mail.log       syslog.5.gz
alternatives.log.3.gz  boot.log       dpkg.log.1     kern.log.1      mail.log.1     syslog.6.gz
alternatives.log.4.gz  bootstrap.log  dpkg.log.2.gz  kern.log.2.gz   mail.log.2.gz  syslog.7.gz
alternatives.log.5.gz  btmp           dpkg.log.3.gz  kern.log.3.gz   mail.log.3.gz  unattended-upgrades
apport.log             btmp.1         dpkg.log.4.gz  kern.log.4.gz   mail.log.4.gz  upstart
apport.log.1           dist-upgrade   dpkg.log.5.gz  landscape       maltrail       wtmp
apport.log.2.gz        dmesg          dpkg.log.6.gz  lastlog         mysql          wtmp.1
apt                    dmesg.0        dpkg.log.7.gz  mail.err        syslog

 

 

OpenSSH[実践]入門 Software Design plus OpenSSH[実践]入門 Software Design plus

リモートサーバでrsync+sudoでログインユーザに権限のないフォルダを同期させる

$
0
0

前にssh越しにsudo経由でtarを用いるという事をやっていたのだが、今回はrsync。で、rsyncもそうみたいなのだが、ssh越しで擬似端末(tty)を使っての通信できないらしい。こうなると、sshで「-tt」オプションを付けて擬似端末を有効にしての対応は難しいので、CentOSなどのデフォルト(AWSとかAzure上のイメージでは手が入ってるので対象外)だとsudo実行時には擬似端末を要求する指定(Defaults requiretty)を解除する必要があるようだ。ユーザごとに設定もできるのだが、面倒であれば以下のようなコマンドを実行してrequirettyを無効化してしまおう。

ssh -t user@host 'sudo sed -i "/requiretty$/s/^/# /g" /etc/sudoers'

疑似端末が要求されないようになったら、あとは以下のようにコマンドを実行することでroot権限が必要になるディレクトリに対するrsyncが行えるようになる。

rsync -auv -e "ssh -i key " --rsync-path="sudo rsync " user@host:/remotedir /localdir

 

で、この時注意したいのがsudo実行時にパスワードが必要な場合。sshコマンドで直接sudoを呼び出しているのと違い、rsync経由でssh接続しているからか、ヒアドキュメントや標準入力を利用してのパスワード入力はちょっと難しいみたい。X11Forwardingを使えるのなら、ssh-askpassを使ってやればなんとかなるようだけど、それ以外の方法はちょっと無さそう。
色々と試してみたけど、基本はやはり/etc/sudoersいじってrequirettyを無効化・NOPASSWDで実行できるようにするのが一番早いようだ。

 

OpenSSH[実践]入門 Software Design plus OpenSSH[実践]入門 Software Design plus

bashのワンライナーで指定したコマンド失敗時にリトライを行わせる

$
0
0

Twitterボケっと見てたところ、指定したコマンド失敗時にリトライをする方法についてのツイートが流れてきたので、個人的にちょっと調べてみた。

回数制限を付けない場合

回数制限を付けない(失敗したらずっとリトライをし続ける)のであれば、untilでやるのが一番短く書けそうだ。

until COMMAND;do sleep 1;done

 

例えば、こんな感じでやると、成功するまでは1秒ごとにリトライをする。

[root@BS-PUB-CENT7-01 ~]# until mkdir $(date +%Y%m%d_%H%M00);do sleep 1;done
mkdir: ディレクトリ `20170615_043200' を作成できません: ファイルが存在します
mkdir: ディレクトリ `20170615_043200' を作成できません: ファイルが存在します
mkdir: ディレクトリ `20170615_043200' を作成できません: ファイルが存在します
mkdir: ディレクトリ `20170615_043200' を作成できません: ファイルが存在します
[root@BS-PUB-CENT7-01 ~]#
[root@BS-PUB-CENT7-01 ~]# ls -la 20170615_043300
合計 4
drwxr-xr-x.  2 root root    6  6月 15 04:33 .
dr-xr-x---. 14 root root 4096  6月 15 04:33 ..
[root@BS-PUB-CENT7-01 ~]# ls -lad 20170615_043300
drwxr-xr-x. 2 root root 6  6月 15 04:33 20170615_043300

回数制限を付ける場合

Twitterで見かけたのはコレなのだが、リトライ回数に制限を付ける場合だと、素直にforを使うのが一番わかりやすい+短く書けるみたいだ。

for i in {1..10};do COMMAND&&break;sleep 1;done
[root@BS-PUB-CENT7-01 ~]# for i in {1..10};do mkdir $(date +%Y%m%d_%H%M00)&&break;sleep 1;done
[root@BS-PUB-CENT7-01 ~]# for i in {1..10};do mkdir $(date +%Y%m%d_%H%M00)&&break;sleep 1;done
mkdir: ディレクトリ `20170615_074200' を作成できません: ファイルが存在します
mkdir: ディレクトリ `20170615_074200' を作成できません: ファイルが存在します
mkdir: ディレクトリ `20170615_074200' を作成できません: ファイルが存在します
mkdir: ディレクトリ `20170615_074200' を作成できません: ファイルが存在します
mkdir: ディレクトリ `20170615_074200' を作成できません: ファイルが存在します
mkdir: ディレクトリ `20170615_074200' を作成できません: ファイルが存在します
mkdir: ディレクトリ `20170615_074200' を作成できません: ファイルが存在します
mkdir: ディレクトリ `20170615_074200' を作成できません: ファイルが存在します
mkdir: ディレクトリ `20170615_074200' を作成できません: ファイルが存在します
mkdir: ディレクトリ `20170615_074200' を作成できません: ファイルが存在します

 

ちなみに、untilで書くとちょっと複雑になってしまうようなのであまりオススメはしない。

(i=0;until COMMAND||[ $i -eq 5 ];do sleep 1;((i++));done)

 

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

Linuxでログを集計できる『petit』コマンドを使ってみる

$
0
0

ぼけーっとネットで調べ物してたところ、ログの簡単な集計・分析用のコマンド『petit』なるものを見かけたので、ちょっと試してみた。
Debian/Ubuntu系であればaptから、RHEL系であればrpmファイルを指定してyumからインストールできるようだ。

sudo apt install petit
yum install -y http://crunchtools.com/wp-content/files/petit/petit-current.rpm

 

インストールができたら、以下のようにコマンドを実行することでログを集計することができる。

petit --hash LogPath
[root@BS-PUB-CENT7-01 ~]# petit --hash /var/log/messages
638: systemd: Created slice user-#.slice.
638: systemd: Removed slice user-#.slice.
638: systemd: Starting user-#.slice.
638: systemd: Stopping user-#.slice.
490: systemd: Started Session # of user apache.
490: systemd: Starting Session # of user apache.
149: systemd-logind: Removed session #.
92: systemd-logind: New session # of user test.
92: systemd: Started Session # of user test.
92: systemd: Starting Session # of user test.
72: systemd: Started Session # of user root.
72: systemd: Starting Session # of user root.
56: systemd-logind: New session # of user test#.
56: systemd: Started Session # of user test#.
56: systemd: Starting Session # of user test#.
4: su: (to test) root on pts/#
3: Started Cleanup of Temporary Directories.
3: Starting Cleanup of Temporary Directories...
2: New session 4573 of user root.
1: [origin software="rsyslogd" swVersion="7.4.7" x-pid="981" x-info="http://www.rsyslog.com"] rsyslogd was HUPed
1: Installed: 1:cups-libs-1.6.3-26.el7.x86_64
1: Installed: atk-2.14.0-1.el7.x86_64
1: Installed: gdk-pixbuf2-2.31.6-3.el7.x86_64
1: Installed: gtk2-2.24.28-8.el7.x86_64
1: Installed: hicolor-icon-theme-0.12-7.el7.noarch
1: Installed: jasper-libs-1.900.1-30.el7_3.x86_64
1: Installed: jbigkit-libs-2.0-11.el7.x86_64
1: Installed: libXcomposite-0.4.4-4.1.el7.x86_64
1: Installed: libXcursor-1.1.14-2.1.el7.x86_64
1: Installed: libXi-1.7.4-2.el7.x86_64
1: Installed: libXinerama-1.1.3-2.1.el7.x86_64
1: Installed: libXrandr-1.4.2-2.el7.x86_64
1: Installed: libtiff-4.0.3-27.el7_3.x86_64
1: Installed: openssh-askpass-6.6.1p1-35.el7_3.x86_64
1: Installed: petit-1.1.1-1.i386

色々とオプションがあるようだ。キーワードの頻出なんかもある様子(grepやawk組み合わせれば同様の事できるが)。以下、helpの出力結果。

[root@BS-PUB-CENT7-01 ~]# petit --help
Usage: petit [options] [file]

Options:
  -h, --help     show this help message and exit
  -v, --verbose  Show verbose output
  --sample       Show sample output for small numbered entries
  --nosample     Do not sample output for low count entries
  --allsample    Show samples instead of munged text for all entries
  --filter       Use filter files during processing
  --nofilter     Do not use filter files during processing
  --wide         Use wider graph characters
  --tick==TICK   Change tick character from default
  --fingerprint  Use fingerprinting to remove certain patterns
  -V, --version  Show verbose output
  --hash         Show hashes of log files with numbers removed
  --wordcount    Show word count for given word
  --daemon       show a report of entries from each daemon
  --host         show a report of entries from each host
  --sgraph       show graph of first 60 seconds
  --mgraph       show graph of first 60 minutes
  --hgraph       show graph of first 24 hours
  --dgraph       show graph of first 31 days
  --mograph      show graph of first 12 months
  --ygraph       show graph of first 10 years

 

ちょっとした集計処理なんかに悪くなさそう。

 

Windows/Linuxのトラブル追跡実践ノウハウ エンジニア必携 Windows/Linuxのトラブル追跡実践ノウハウ エンジニア必携

sudoで覚えておくと便利な設定・使い方

$
0
0

最近、色々とsudoで設定を変えたりすることが多かったので調べてみたら、結構色々な設定やsudoコマンドのオプションとかがあるようだったので、調べた内容から基本的な設定や便利そうな使い方についてまとめてみることにした。
なお、/etc/sudoersではなくLDAPでもポリシー設定はできるようなのだが、あまり使うパターンも少ないだろうから今回は割愛する。SELinuxのポリシー設定についても設定はできるようなのだが、今回は割愛する。なお、検証にはCentOS 7の以下のバージョンを用いている。

[root@BS-PUB-CENT7-01 test]# sudo -V | head -1
Sudo バージョン 1.8.6p7

/etc/sudoersの設定について

sudoコマンドのポリシー設定は、/etc/sudoers(includeさせるなら、/etc/sudoers.d/配下のファイルに記述を分ける事もできる)で設定する。
sudo自体は特にサービスとして動いているものではないので、ファイルを変更したら設定は即時反映される。

編集自体はvimなどのエディタで普通にいじることができるのだが、保存時に構文チェックを行ってくれるvisudoコマンドで編集するのが良いだろう。

基本的な書き方

基本的な書き方は単純で、以下のようにデフォルトで適用させるオプション値とユーザごとで適用させるポリシーを書いてやればよい(Aliasとかも設定できるのだが後述)。

Defaults オプション # sudoで適用させるオプション
Defaults !オプション # sudoで適用させるオプション(頭に!を付けると明示的に無効化できる)
Defaults:ユーザ名 !オプション # ユーザごとにオプションの有効化・無効化を指定する
...

ユーザ名 対象ホスト=(コマンドを実行させるユーザ・グループ) TAG(実行可能・不可能なコマンドやNOPASSWDなど) # ユーザごとの設定値
ユーザ名 対象ホスト=(コマンドを実行させるユーザ・グループ) TAG,TAG # TAGは複数設定できる
ユーザ名 対象ホスト=(コマンドを実行させるユーザ・グループ1) TAG,(コマンドを実行させるユーザ・グループ2) TAG # このような区切りもできる

%グループ名 対象ホスト=(コマンドを実行させるユーザ・グループ) TAG # sudoコマンドを実行するグループごとでの設定
...
includedir DIRPATH # 設定を外に出してある、インクルードするディレクトリ(基本は/etc/sudoers.d)

エイリアスについて

/etc/sudoersでは、ユーザやグループ、実行可能なコマンドなどについてエイリアスを定義して、それを設定に利用する事ができる。
設定できるエイリアスは「User_Alias」「Runas_Alias」「Host_Alias」「Cmnd_Alias」の4種類(Host_Aliasは使うこと無いような気もするけど)。以下のように設定することができる。

User_Alias   エイリアス名 = ユーザ1,ユーザ2,ユーザ3
Runas_Alias  エイリアス名 = ユーザ名:グループ名
Cmnd_Alias   エイリアス名 = コマンドPATH1,コマンドPATH2

これを利用することで、以下のように/etc/sudoersを記述することができる。複数のユーザやグループがいて、それぞれに設定がある場合にはエイリアスを使うことで簡潔に記述することができる。
(まぁ、以下の例だと同一サブグループで同一のグループに所属させて%グループ名で指定してやる方法でもいけるが…)

User_Alias   TESTUSER = test1,test2,test3

TESTUSER     ALL=(ALL) NOPASSWD: ALL

Defaultsで設定できるオプション

sudoersで、Defaultsで設定できるオプションは結構多く、その中には使ってる最中に引っかかるものもあったりする。
manを見るとかなり種類があるので、便利そうなの、変なの、よく使いそうなもの、ディストリビューションによってはよくデフォルトで設定されているものを抜粋する(詳細はmanを参照)。

  • always_set_home … 環境変数$HOMEを変身対象ユーザ(指定がない場合はデフォルトでroot)のホームディレクトリに設定する。デフォルトでは無効。
  • authenticate … 有効にしておくと、sudoコマンド実行ユーザはパスワード認証などでの認証が求められる(ユーザごとの設定でNOPASSWDなどで上書き変更可能)。デフォルトで有効。
  • insults … 有効にしておくと、パスワードの入力間違い時に英文で悪態を付いてくる。使うにはコンパイル時にオプションを有効にしておく必要がある(RHEL系ではコンパイル時に無効になってる様子)。デフォルトでは無効。
  • log_output … sudoコマンドによるスクリーンへの出力結果を全て特定のファイルに取得する(入力結果をログに出すlog_inputもあるが、あまり利用しないと思うので省略)。つまり、sudoを経由したコマンドでscriptコマンドのような使い方ができる。デフォルトでは無効。詳細は後述。
  • logfile = ログファイルPATH … デフォルトではsudoのログはsyslog経由で出力されるが、指定されたPATHに出力されるようになる。デフォルトでは無効。
  • iolog_dir = ディレクトリPATH … log_output、log_inputで取得されるログの出力先ディレクトリのPATHが指定できる。出力先にはstrftimeの変数(%Y%m%dでYYYYMMDDとか)の他、以下の変数が使用可能。
    • %{seq}
    • %{user}
    • %{group}
    • %{runas_user}
    • %{runas_group}
    • %{hostname}
    • %{command}
  • iolog_file = ログファイルPATH … log_output、log_inputで取得されるログの出力先ファイルのPATHが指定できる。iolog_dirと同じように、出力先には変数が使用可能。詳細は後述。
  • syslog = ログレベル … sudoの動作ログについて、syslog経由で指定したログレベルで出力する。デフォルトではauthprivになっている。
  • syslog_badpri = ログレベル … sudo実行ユーザが不正なパスワード入力時にsyslogに記録するログレベル。デフォルトではalertになっている。
  • syslog_goodpri = ログレベル … sudo実行ユーザが正しいパスワード入力時にsyslogに記録するログレベル。デフォルトではnoticeになっている。
  • mail_always … sudoコマンドが実行されるたびにmailtoオプションで指定したアドレスにメールを送信する
  • mailfrom = メールアドレス … メール送信時に送信元となるメールアドレス。記述時は@をダブルクォーテーションで囲むこと。
  • mailto = メールアドレス … メール送信先のメールアドレス。記述時は@をダブルクォーテーションで囲むこと
  • noexec … sudoを経由して実行されるコマンドが、EXECタグで無効にされない限りNOEXECでの動作(sudoで実行したプログラムから他のプログラムを起動させない)になる。デフォルトでは無効。
  • requiretty … sudoの実行に擬似端末(tty)を要求する。つまり、このオプションが有効になっている場合、sudoの実行できるのはログインセッション(sshで擬似端末を要求した場合含む)だけで、cronなどからの実行を許可させない。デフォルトでは無効(RHEL系のディストリビューションでは設定ファイルで有効にされている場合がある)。
  • root_sudo … rootもsudoが実行できるようになる。これが無効化されていると、rootユーザでsudoeditなどが利用できなくなる。デフォルトで有効。
  • rootpw … sudo実行時に、ユーザのパスワードではなくrootのパスワードを求められるようになる。デフォルトでは無効。
  • targetpw … sudo実行時に、ユーザのパスワードではなく-uで指定されたユーザのパスワード(デフォルトはroot)を求められるようになる。デフォルトでは無効。
  • visiblepw … 有効にすると、sudo実行時にパスワードがスクリーンに表示されてしまう場合でもプロンプトを表示していパスワード入力を受け付けるようになる(デフォルトではエラーが表示される)。デフォルトでは無効。
  • verifypw = パターン … sudoコマンドを-vオプション付きで実行した際、ユーザがパスワードを要求されるのはどういう場合かを指定する。指定できるパターンは以下。
    • all … パスワードの入力を回避するには、sudoersの使用中ホストに対するユーザの全エントリーにNOPASSWDタグが設定されている必要がある。
    • always … -vオプション付きでsudoを実行した場合、必ずパスワードの入力を求められるようになる。
    • any … パスワードの入力を回避するには、sudoersの使用中ホストに対するユーザのエントリーに最低一つはNOPASSWDタグが設定されている必要がある。
    • never …  -vオプション付きでsudoを実行した場合、パスワードの入力を求められなくなる。
  • listpw = パターン … sudoコマンドを-lオプション付きで実行した際、ユーザがパスワードを要求されるのはどういう場合かを指定する。指定できるパターンは↑のverifypwと同じ。
  • passwd_tries = Num … パスワードの試行回数を設定できる。デフォルトは3回。
  • badpass_message = “メッセージ(文字列)” … 間違えたパスワード入力時のメッセージを、指定したメッセージに変更する。
  • passprompt = “プロンプトメッセージ(文字列)” … sudoコマンドから実行時のパスワード入力プロンプトを、指定したプロンプトに変更する。
  • shell_noargs … このオプションが有効の場合、-sが指定されたとみなしrootユーザでシェルが実行される。デフォルトでは無効。
  • use_pty … このオプションが有効の場合、sudoは入出力ロギングが無効の場合でも疑似ttyでコマンドを実行するようになる。
  • lecture = パターン … このオプションが有効の場合、sudo実行時に警告(というか訓戒。管理者としての心構えなど)を表示するようになる。指定できるパターンは以下。なお、パターンを指定しない場合、onceが指定される。
    • always … 常時警告を表示させる
    • never … 常時警告を表示させない
    • once … ユーザが初めてsudoを実行した際に表示させる
  • lecture_file = ファイルPATH … lectureオプション有効時に表示させる警告の内容を、指定したファイルPATHの内容に書き換える。

ユーザ・グループごとのポリシー設定(TAG)

ユーザ・グループごとのポリシー設定(このユーザ・グループはsudoを使えるとか、どのコマンドを使用できるかなど)は、TAGで設定することができる。

ユーザ名 対象ホスト=(コマンドを実行させるユーザ・グループ) TAG(実行可能・不可能なコマンドやNOPASSWDなど)

設定可能なTAGは以下。

  • EXEC/NOEXEC … sudo経由で実行したプログラムから、さらにプログラムを呼び出せるか否か(対象のプログラムがNOEXECに対応している必要がある)。
  • FOLLOW/NOFOLLOW … sudo経由で実行したプログラムで、シンボリックリンクをたどるかどうか。
  • LOG_INPUT/NOLOG_INPUT … ユーザのインプットをログに記録するかどうか。
  • LOG_OUTPUT/NOLOG_OUTPUT … スクリーンへのアウトプットをログに記録するかどうか。
  • MAIL/NOMAIL … ユーザがsudo経由でコマンド実行時にメールを送信するか否か。
  • PASSWD/NOPASSWD … ユーザがsudo実行時にパスワード入力を要求するか否か。
  • SETENV/NOSETENV … ユーザがsudo実行時に環境変数を継承するか否か。

よく使いそうな設定・使用例

sudoの設定で、個人的によく使いそうな設定について記述してみる。

ユーザに特定のコマンドのみ実行を許可する

結構よく使う設定。単純に、以下のように対象のプログラムのPATHを指定してやれば良い。

ユーザー  ALL=(ALL) コマンドPATH

ユーザに特定のコマンドのみ実行を許可しない

基本的にはどのコマンドも使ってよいが、ある特定のコマンドのみを許可したくない場合、以下のように続けて!で対象のコマンドPATHを指定する。

ユーザー  ALL=(ALL) ALL,!コマンドPATH

 

以下、実際にlsコマンドのみを実行不可にした場合。

[test1@BS-PUB-CENT7-01 ~]$ sudo cat /etc/sudoers | grep ^test1
test1   ALL=(ALL)       ALL,!/usr/bin/ls
[test1@BS-PUB-CENT7-01 ~]$ sudo pwd
/home/test1
[test1@BS-PUB-CENT7-01 ~]$ sudo ls -la
ユーザー test1 は'/bin/ls -la' を root として BS-PUB-CENT7-01.blacknon.local 上で実行することは許可されていません。すみません。

特定のコマンドのみパスワード入力ありで実行できるようにしたい

基本的にはどのコマンドもNOPASSWDでパスワード入力を省略させたいが、特定のコマンド(エイリアスでの設定含む)のみパスワード認証をさせたい場合、以下のように記述する。
もちろん、この逆で特定のコマンドのみパスワード入力なしも可能だ。

ユーザ  ALL=(ALL) NOPASSWD: ALL,PASSWD: コマンドPATH

 

以下、実際にsuコマンドのみをパスワード要求するように設定した場合。

[test@BS-PUB-CENT7-01 ~]$ sudo cat /etc/sudoers | grep -E "^test\s"
test    ALL=(ALL)       NOPASSWD: ALL,PASSWD: /usr/bin/su
[test@BS-PUB-CENT7-01 ~]$ sudo pwd
/home/test
[test@BS-PUB-CENT7-01 ~]$ sudo su

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for test:
[root@BS-PUB-CENT7-01 test]#

sudo経由での操作(出力内容・ターミナルログなど)をログに記録・再生する

sudo経由での操作をscriptコマンドのように自動的にログに記録するには、以下のようにする。

Defaults    log_output
Defaults    iolog_dir = ログ出力先ディレクトリ # デフォルトの/var/log/sudo-io以外にする場合

 

設定後は、バイナリファイルでターミナルでの操作タイミングや出力データを保存する。
保存された操作ログは、sudoreplayで再生することができる。イメージ的には、scriptreplayでのターミナル操作の再生に近い。

sudoreplay [-d iolog_dir(デフォルトだと/var/log/sudo-io)] ログ番号

 

例えば、「/var/log/sudo_io/00/00/02」のログを再生する場合は、以下のようにコマンドを実行する。

sudoreplay 000002

 

sudoreplayで再生できるログは、以下のコマンドで確認できる。

sudoreplay -l
[root@BS-PUB-CENT7-01 test]# sudoreplay -l
 6月 17 19:39:27 2017 : root : TTY=/dev/pts/4 ; CWD=/root ; USER=root ; TSID=000001 ; COMMAND=/bin/su - test
 6月 17 19:39:42 2017 : test : TTY=/dev/pts/5 ; CWD=/home/test ; USER=root ; TSID=000002 ; COMMAND=/usr/bin/su -
 6月 17 19:39:49 2017 : test : TTY=/dev/pts/5 ; CWD=/home/test ; USER=root ; TSID=000003 ; COMMAND=/bin/bash
 6月 17 20:01:00 2017 : test : TTY=/dev/pts/4 ; CWD=/home/test ; USER=root ; TSID=000004 ; COMMAND=/bin/ls -la
 6月 17 20:01:04 2017 : test : TTY=/dev/pts/4 ; CWD=/home/test ; USER=root ; TSID=000005 ; COMMAND=/bin/pwd
 6月 17 20:45:53 2017 : root : TTY=/dev/pts/4 ; CWD=/root ; USER=root ; TSID=000006 ; COMMAND=/bin/vi ./test.txt
...

 

残念ながらscriptコマンドのようにawkと組み合わせて行頭にタイムスタンプの付与は難しそうだが、sudoを経由しての処理のみをログに残しておくと考えると悪くはなさそうだ(suでrootユーザに切り替えられた後のbashの操作もログに残しておけるので)。

cronやssh経由でもsudoを使えるようにする

cronやssh経由(それでも-ttオプションつければいけるのだが…)でsudoを使う場合、「requiretty」オプションが付いていると擬似端末を要求されるため、sudoを使用できない事がある(CentOSなど、RHEL系だとOSインストール時に有効化されていたりする)。そんなときは、対象の処理をコメントアウトして無効化するか、もしくは以下のように対象のユーザのみで「requiretty」を無効化してやるようにしたらよい。

Defaults:ユーザ名 !requiretty

sudoコマンドについて

/etc/sudoersの設定を終えて、実際にsudoコマンドを実行する際、色々な使い方がある。

コマンドを実行するユーザ・グループを指定する

sudoでは、実行するコマンドについて-uでユーザ、-gでグループを指定して実行することができる。

sudo -u ユーザ コマンド
[test@BS-PUB-CENT7-01 ~]$ sudo -u test1 id
uid=1004(test1) gid=1004(test1) groups=1004(test1),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

 

sudoで実行可能なコマンドのリストを確認する

-lオプションを付与することで、そのユーザで実行可能なプログラムや適用されるsudoers設定について確認することができる。

sudo -l
sudo -l -U ユーザ
[test@BS-PUB-CENT7-01 ~]$ sudo -l
このホスト上でユーザー test に一致したデフォルト項目:
    !visiblepw, lecture=always, always_set_home, log_output, iolog_dir=/var/log/sudo_log,
    env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL
    PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION
    LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER
    LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY",
    insults, secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin

ユーザー test は次のコマンドをこのホスト上で実行できます:
    (ALL) NOPASSWD: ALL, (ALL) PASSWD: /usr/bin/su
[test@BS-PUB-CENT7-01 ~]$ sudo -l -U test1
このホスト上でユーザー test1 に一致したデフォルト項目:
    !visiblepw, lecture=always, always_set_home, log_output, iolog_dir=/var/log/sudo_log,
    env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL
    PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION
    LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER
    LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY",
    insults, secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin

ユーザー test1 は次のコマンドをこのホスト上で実行できます:
    (ALL) ALL, (ALL) !/usr/bin/ls

プログラムをバックグラウンド実行させる

sudoで実行するプログラムをバックグラウンドで実行させたい場合、-bオプションを付与すると良いだろう。
出力結果は

sudo -b コマンド

 

出力結果はターミナルに表示される。vmstatなどを定期実行させてその結果をリダイレクトでファイルに書き出すときなどに有効だ。

パスワード入力を標準入力(パイプとか)から行わせる

パスワードをプロンプト表示させず、パイプなどから受け付けて処理させる場合、-Sオプションを付与する。

echo password | sudo -S コマンド
[test2@BS-PUB-CENT7-01 ~]$ echo P@ssw0rd | sudo -S id
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

 

ssh越しにrequirettyを有効にした状態でsudoコマンドを実行するなんかには、以下のようにコマンドを実行すると良いだろう。

ssh user@hostname 'echo password | sudo -S cmd 2>/dev/null'

パスワードを聞かれるようにする

パスワードを特定のプログラム(x11のaskpassなど)から聞かれる用にする場合、-Aオプションを付与する。
これを利用することで、例えば擬似端末が必要な環境でx11forwardingを経由してのssh越しのsudo実行といった事が可能になる。

SUDO_ASKPASS=プログラムPATH sudo -A コマンド

パスワードプロンプトを任意の文字列にする

パスワードプロンプトに任意の文字列を使用する場合、-pオプションで指定することができる。

sudo -p "prompt" コマンド
[test2@BS-PUB-CENT7-01 ~]$ sudo -p "test password prompt:" ls -la

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

test password prompt:
合計 16
drwx------. 2 test2 test2  79  6月 18 03:02 .
drwxr-xr-x. 6 root  root   52  6月 18 03:02 ..
-rw-------. 1 test2 test2   5  6月 18 03:02 .bash_history
-rw-r--r--. 1 test2 test2  18 12月  7  2016 .bash_logout
-rw-r--r--. 1 test2 test2 193 12月  7  2016 .bash_profile
-rw-r--r--. 1 test2 test2 231 12月  7  2016 .bashrc

認証をリセットする

次回以降sudoを利用する際、再度パスワードを求められるよう認証状況をリセットする場合、-kオプションを付与する。

sudo -k # 認証情報をクリアする
sudo -k コマンド # 認証情報をクリアしてコマンドを実行する(次回以降はデフォルトの動作)

シェルにログインする

単純にログインシェルを切り替える場合、suコマンドを使わずとも、以下のように-iもしくは-sオプションを利用することでシェルを起動できる。

sudo -i # 対象ユーザのログインシェル
sudo -s # 環境変数$SHELLもしくは対象ユーザのログインシェル

 

【参考】

 

動くメカニズムを図解&実験! Linux超入門 (My Linuxシリーズ) 動くメカニズムを図解&実験! Linux超入門 (My Linuxシリーズ)
Viewing all 498 articles
Browse latest View live




Latest Images