読者です 読者をやめる 読者になる 読者になる

ITを基礎からやってくブログ

とにかく基礎からやってくんです。基礎が大事なんです。

Windowsイベントログをコマンドでエクスポートする

Windowsイベントログをコマンドでエクスポートするのは、一定の需要があるようなので調べてみた。
エクスポートは、あとからイベントビューアで読み込めるevtx形式で行う前提。

1. PowerShellの場合

まず何かと便利なPowerShellで調べてみると、Get-EventLogまたはGet-WinEventコマンドレットが使えそうな空気を醸し出すが、evtx形式でのエクスポートには対応していない。
標準出力をCSVXMLに整形してファイルに保存する方法はいくつか見当たるが。。

ヘルプはこちら。 Get-WinEvent

-ComputerNameや-Credentialを指定することで他のマシンのログも取得できるようなので、そこは利点。
-Pathでevtxファイルを指定すれば、ファイルから読み取ることも可。
フィルタには、ある程度のところまで-FilterHashTableでフィルタして負荷を減らしつつ、Where-Objectで絞り込むのが吉と思われる。

# Systemログからログレベル「重大」、イベントID 10116 をフィルタ後、「keyword」を含むメッセージで絞り込む
Get-WinEvent -FilterHashtable @{LogName='system';Level=1;ID=10116} | Where-Object{ $_.Message -match "keyword" }

2. コマンドプロンプトの場合

wevtutilコマンドでevtx形式のエクスポートができる。

wevtutil export-log [イベントログの種類] [エクスポート先ファイルパス]
rem 例)wevtutil export-log system System.evtx

ヘルプはこちら。 Wevtutil

全件保存なら何も難しくないが、フィルタしようとすると/q: <Query>という形でXML Filterっていう面倒なクエリを書かないといけない*1ので、 フィルタするならevtx形式保存はあきらめて、後からGet-WinEventでフィルタしてテキスト保存するほうが楽か。

ログレベルやイベントIDでのフィルタくらいならそれほど難しくはないけれど、面倒なのに変わりはない。

rem ログレベルを指定して保存 重大:1 エラー:2 警告:3 情報:4
wevtutil export-log system System.evtx /q:"*[System[Level = 2]]"

rem イベントID 7031 だけを保存
wevtutil export-log system System.evtx /q:"*[System[EventID = 7031]]"

rem AND条件
wevtutil export-log system System.evtx /q:"*[System[(Level = 2) and (EventID = 7031)]]"

rem OR条件
wevtutil export-log system System.evtx /q:"*[System[(Level = 1 or Level = 2)]]"

まとめ

  • evtx形式で保存したい → wevtutilコマンドを使って全件保存。フィルタしたいならXMLクエリを頑張って書く。
  • evtx形式にはこだわらない。むしろ楽にフィルタしたい → Get-WinEvent

cronでメール送信時にNSS関連のエラー

CentOS6.5にて、mailコマンドでメールを送るシェルをcronで動かしていたのだけど、 メールが来ない事象が発生。

  • コマンド
mail -v -s "タイトルほげほげ" \
   -r xxxxxxxxxxxxx@gmail.com \
   -S smtp-use-starttls \
   -S smtp=smtp://smtp.gmail.com:587 \
   -S smtp-auth=login \
   -S smtp-auth-user=xxxxxxxxxxxxx@gmail.com \
   -S smtp-auth-password=yyyyyyyyyyyyyyyyy\
   -S nss-config-dir=~/cert \
   -S ssl-verify=ignore \
   xxxxxxxxxxxxx@gmail.com
  • エラー内容

Error initializing NSS: Unknown error -8015.

シェルを直接叩くと正常に送信されるので、cronの問題だと思って調査したところ、 原因が2つ判明。

1. 環境変数

cronでトラブル時は、環境変数の問題であることが多い、とのこと。

CentOSでcronからphp mail送れない - Linux系OS 締切済 | 教えて!goo

コマンド内で環境変数じみている箇所は、、、

-S nss-config-dir=~/cert \

ここですね。エラーメッセージとも一致します。

チルダ(~)って環境変数扱いなんだっけ?と思って調べたら、 下記の記述を発見。

bashのチルダ展開、~ と ~name の違い – Imai blog

自分でも試してみた。

/etc/crontab
* * * * * root echo "1" ~ >> /root/cronlog
* * * * * root echo "2" ~root >> /root/cronlog
* * * * * root echo "3 $HOME" >> /root/cronlog
実行結果
1 /
2 /root
3 /

上記記事と同様、~と$HOMEは/を、~rootは/rootを示しました。

cron内では、明示的にパスを書く、またはチルダの後に明示的にユーザ名を書くほうの記載をする必要があるようです。

-S nss-config-dir=/root/cert \

または

-S nss-config-dir=~root/cert \

2. SELinux

Bug 919038 – SELinux is preventing /usr/bin/mailx from 'write' accesses on the directory /.

出た。何かと邪魔してくるSELinux。いやセキュリティ必要なところならいいことなんだけど。

今回はセキュリティはほぼ気にする必要のないローカル環境だったのでオフ。 ていうかなんで有効のままにしてたんだろう。

setenforce 0

以上でcronからメール送信が問題なくできるようになりました。

基礎からWebアプリ#3

基礎からWebアプリ#3です。

2.Java Servlet (Tomcat利用)

JDKインストール

OpenJDK1.7でいきます。

yum -y install java-1.7.0-openjdk-devel

Tomcatインストール

Tomcat公式ページによると、Java1.7に対応している最新は8.0系です。
Tomcat8を入れます。

まずは起動用のユーザを作成。
セキュリティの観点から、普通nologin設定で作成します。

useradd -s /sbin/nologin tomcat

次にインストール。

# Tomcatバイナリダウンロード
wget http://ftp.tsukuba.wide.ad.jp/software/apache/tomcat/tomcat-8/v8.0.33/bin/apache-tomcat-8.0.33.tar.gz
# /usr/local配下に解凍
# -Cオプションをつけることで、解凍先のフォルダへcdする手間が省けます。
tar -C /usr/local -zxvf apache-tomcat-8.0.33.tar.gz
# 権限をtomcatユーザに設定
chown -R tomcat:tomcat /usr/local/apache-tomcat-8.0.33
# tomcatインストールディレクトリへのシンボリックリンク作成
ln -s /usr/local/apache-tomcat-8.0.33 /usr/local/tomcat

Tomcat起動

同梱の起動シェルをtomcatユーザで実行します。

sudo -u tomcat /usr/local/tomcat/bin/startup.sh 

JAVA_HOMEとかCATALINA_HOMEとかはstartup.shの中の処理で自動で認識してくれるみたいです。
確実にやるなら/etc/profileか、Tomcatのbinにsetenv.shを作成して書いておく必要があります。

また、サーバとして使うなら本当は自動起動設定とかするべきなんだけど、今回は置いておきます。

Tomcatの詳細についてはググる"Google検索:tomcat linux 入門"

環境変数等の設定

環境変数を設定します。
先述の通り、tomcat起動時は必要な環境変数をいい感じに自動設定してくれますが、 tomcatユーザ以外にも明示的に環境変数を指定しておいたほうが無難なので設定します。
/etc/profileに環境変数を書けば全ユーザに反映されます。
以下を追記。

export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk.x86_64 //同じ階層にJREのディレクトリもあるので間違えないよう
export CATALINA_HOME=/usr/local/tomcat
export CLASSPATH=".:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar:$CATALINA_HOME/lib/*"

CLASSPATHは、ディレクトリ指定で書く場合、そのディレクトリに入っている.classファイルは読み込んでくれますが.jarファイルは読み込んでくれません。
.jarファイルを読み込むにはファイル名を明示するか、*を書いてあげる必要があります。

コンパイル時に明示的に指定してもいいです。
servlet関連のjarなら、javac -cp $CATALINA_HOME/lib/servlet-api.jar [javaソースファイル名])

/etc/profileはユーザログイン時に一度だけ読み込まれますが、ひとまず今は強制読込しておきます。

source /etc/profile
続きを読む

基礎からWebアプリ#2

基礎からWebアプリ#2です。

1. まずはHTMLだけで (Apache利用)

Apacheのインストール

yum -y install httpd
sed -i -e "/#ServerName www.example.com:80/i ServerName `hostname`" /etc/httpd/conf/httpd.conf
service httpd start

まずは動かすことが目的なので細かいことは考えない。
最低限としてServerNameにホスト名だけ入れて、httpdを起動する。
Apacheについてはググる"Google検索:apache 入門"

HTMLファイル作成

/var/www/html/tableview.htmlを以下の通り作成。
HTMLファイルを書いて置くだけなので、簡単ですね。

<html>
<head>
<title>daily report</title>
<style type="text/css">
table {
    border-collapse: collapse;
    width: 500px;
}
th {
    text-align: center;
    border: solid 1px;
    padding: 0.5em;
    background-color: #6666FF;
}
td {
    text-align: center;
    border: solid 1px;
    padding: 0.5em;
}
</style>
</head>

<body>

<table>
<tr>
<th>日付</th>
<th>体重</th>
<th>体脂肪率</th>
<th>内臓脂肪レベル</th>
</tr>
<tr>
<td>2016/4/8</td>
<td>65.6</td>
<td>14.0</td>
<td>5</td>
</tr>
</table>

</body>
</html>

CSSで表のスタイルを少し入れています。
CSSはよくわかっていないのでメモ。
(抜粋)

table {
    border-collapse: collapse;・・・線を細くする
}
th {・・・表題になる列
    text-align: center;・・・中央揃え
    border: solid 1px;・・・枠線。飾りのない普通の線、太さ1px
    padding: 0.5em;・・・文字と枠線との間のサイズ
    background-color: #6666FF;・・・背景色
}
td {
    text-align: center;
    border: solid 1px;
    padding: 0.5em;
}

そしてブラウザでつなぐとこう見えます。

http://hostname/tableview.html

f:id:quatrefromage:20160409005026p:plain

次回は 2.Java Servlet (Tomcat利用) です。

基礎からWebアプリ#1

Webアプリを基礎からやろうと思います。
なぜかというと、部分部分の要素技術はちょいちょい触ったり勉強したりするのに、結局全体で具体的にどんな作業をすればどんなものが出来上がるのか感覚がない、という状況を打破したかったからです。
小さいシステムをいくつも作っていれば自然と身につきそうですが受け身だとそうもいかないので。
少しずつ段階を追って、じっくりやっていきます。

題材は「毎日の体重などを記録するアプリ」

目次

  1. まずはHTMLだけで (Apache利用)
  2. Java Servlet (Tomcat利用)
  3. JSP (Tomcat利用)
  4. DB化 (PostgreSQL利用)

ここまででいわゆるWeb3層アーキテクチャになります。
この先はできてから考えます。随時追記予定。
クライアント側をリッチにしたり、サーバ側をモダンなアーキテクチャに作り変えていったり、スマホアプリをクライアントにするようなことをやってみたい。

なぜJava(Tomcat)とPostgreSQLなのか?それは仕事で馴染みがあるのがたまたまこのへんのミドルだったからです。

環境はCentOS6で。本当は7も勉強しなきゃと思いつつそれはまた今度。。

シェルスクリプト内に書いたsshコマンドの接続先でsshを実行する

ssh接続のテストをシェルでしようと思って考えていたときにわかったこと。

ssh接続のテストというのは、hostAからhostBへのssh接続がうまくいくかどうかのテストという意味で、 これをhostA、hostBとは別のマシンhostLocalから行いたいということ。

hostLocal --(ssh)--> hostA --(ssh)--> hostB

単純に考えると

ssh <UserName>@<IP1> "ssh <UserName>@<IP2> 'date;hostname;id'"

でいけるかな、と思うのだけど、実際には-tオプションが必要。これがないと2つめのsshでエラーになる。

ssh -t <UserName>@<IP1> "ssh <UserName>@<IP2> 'date;hostname;id'"

-tオプションとは何か?

$ man ssh
(中略) -t Force pseudo-tty allocation. This can be used to execute arbi‐ trary screen-based programs on a remote machine, which can be very useful, e.g. when implementing menu services. Multiple -t options force tty allocation, even if ssh has no local tty.

強制的に擬似端末を割り当てるということらしい。
どうやらsshコマンドは末尾に"コマンド"を書く構文の場合、リソース節約のために擬似端末を割り当てない動作をするようだ。
そのため-tオプションで強制的に擬似端末を割り当ててやることで、接続先でのsshもうまく動作する。

以下記事にも解説あり。

sshで多段ログイン - 技術メモ帳

sshで踏み台経由時のショートカット - Qiita

二つめの記事のコメントによると、一般的には多段SSHにはProxyCommandを指定することが多いようだ。
しかしこの場合hostBへの接続でも認証がhostLocalで行われるとのことなので、ssh接続試験がしたいという今回の目的に限っては-tオプションのほうがよい。

パスワード入力をexpectで捌く場合のサンプルスクリプトは以下。
これを応用すれば対象ホストがたくさんあっても自動化できる。
expectのパッケージはローカルにだけ入っていれば動作する。

まあ、各種試験用ツールを使えばもっといい感じにできるとは思うものの。。

#!/bin/bash

IP1="192.168.X.XX"
IP2="192.168.X.YY"

echo -n "Enter Password for $IP1:"
read -s PASS1
echo ""
echo -n "Enter Password for $IP2:"
read -s PASS2
echo ""

expect -c "
set timeout 5
spawn ssh -t root@$IP1 \"ssh root@$IP2 'date;hostname;id'\"
expect \"'s password:\"
send \"$PASS1\n\"
expect \"'s password:\"
send \"$PASS2\n\"
interact
"