前回でjhatを使ってOOM時のヒープ分析を試みたが、時間がかかってしょうがないので、断念。次にEclipseのMemoryAnalyzerを使ってみる。
1.MemoryAnalyzer(MAT)のインストール
MATには、EclipseのPlug-inと、Standalone版があるらしいので、今回はStandaloneで試す。
Versionは現時点(2014/2/15)で1.3.1だった。
http://www.eclipse.org/downloads/download.php?file=/mat/1.3.1/rcp/MemoryAnalyzer-1.3.1.20140107-win32.win32.x86_64.zip
これを解凍して、適当なフォルダにコピーすれば完了らしい(Javaは1.5以上が必要)。
2.起動しMATにhprofデータを読み込ませる
上記コピーしたフォルダのMemoryAnalyzer.exeを起動すると画面が出てくる。
ここからダンプファイルを開いて、「Leak Suspects Report」を選択すると、以下のような画面が出てくる。
うーん、jhatと比べて圧倒的に速いです。
上記画面から「Dominator tree」を選択すると、classとヒープ消費(Retained Heap)の一覧がでてくるので、「Retained Heap」順にソートして、消費量の大きなClassをたどると、大きなものがあるのか?小さなものが沢山あるのか?がわかる。
ただし、これがメモリリークなのかただ負荷がかかったのか?はOOM前のヒープダンプを取得して、比較しながら進める必要がある。その場合は、Javaのオプションも追加して対応が必要。
これでおおよそ、OOMが出た原因は判明する。このレベルであれば楽ちんでしたね。
2014年2月15日土曜日
javaのOutOfMemory時のヒープの分析にチャレンジ(jhat)
javaアプリでOUtOfMemoryが出ているので、ちょっとヒープの中身を見てみた。
環境は以下の通り
・OOMの出た環境
OS:CentOS 6.4(64bit)
tomcat:6.0.35
Java:1.6.0_30
・解析につかったPC(自作PC)
OS:Windows8.1
CPU:3.2GHz 1P4C
MEMORY:16GB
Tool:Java1.7標準でついてくるjhatとEclipseのMemoryAnalyzer
まずはjhatで試してみた。
1.解析対象となるヒープのダンプデータをゲット
hprofによるheapdumpの取得をする。今回は事前に仕込んでいたが、Javaの起動引数で
-XX:+HeapDumpOnOutOfMemoryError
をつけると、OOMが出たときに、java_pid[xxxx.]hprofというヒープのダンプが出力される。
別途の監視システムでOutOfMemoryが出たら自動再起動という仕組みを入れている場合は、
出力仕切る前にサービス再起動されてしまうので、要注意。
今回ヒープが大きかった(Heap 2GB/Perm 512MB)からか、hprofのサイズが3GBにもなった。
※参考
http://docs.oracle.com/javase/jp/7/technotes/samples/hprof.html
2.jhatにかましてみる
上記でゲットしたhprofファイルをjhatで開いてみる。
#jhat java_pid24328.hprof
結構いいPCを使っているなのだが、CPUが張り付いた。でもっていつまでたっても終わらない。
プロセスを見るとメモリが(PrivateWorkingSet)が3GB付近で止まっている。何か怪しい・・
ということで、オプションをつけて再度確認
#jhat -J-verbose:gc java_pid24328.hprof
GCが結構な頻度で実行されている。
#jhat -J-verbose:gc -J-mx6000m -J-ms6000m java_pid24328.hprof
で再実行。さっきよりはもちろん頻度は落ちたが、まだFullGCが出る(そしてFullGC 1回に15秒くらいかかっている)。だんだんFullGCの頻度が上がってきた。。まだ足りないか・・
#jhat -J-verbose:gc -J-mx10000m -J-ms10000m java_pid24328.hprof
環境は以下の通り
・OOMの出た環境
OS:CentOS 6.4(64bit)
tomcat:6.0.35
Java:1.6.0_30
・解析につかったPC(自作PC)
OS:Windows8.1
CPU:3.2GHz 1P4C
MEMORY:16GB
Tool:Java1.7標準でついてくるjhatとEclipseのMemoryAnalyzer
まずはjhatで試してみた。
1.解析対象となるヒープのダンプデータをゲット
hprofによるheapdumpの取得をする。今回は事前に仕込んでいたが、Javaの起動引数で
-XX:+HeapDumpOnOutOfMemoryError
をつけると、OOMが出たときに、java_pid[xxxx.]hprofというヒープのダンプが出力される。
別途の監視システムでOutOfMemoryが出たら自動再起動という仕組みを入れている場合は、
出力仕切る前にサービス再起動されてしまうので、要注意。
今回ヒープが大きかった(Heap 2GB/Perm 512MB)からか、hprofのサイズが3GBにもなった。
※参考
http://docs.oracle.com/javase/jp/7/technotes/samples/hprof.html
2.jhatにかましてみる
上記でゲットしたhprofファイルをjhatで開いてみる。
#jhat java_pid24328.hprof
結構いいPCを使っているなのだが、CPUが張り付いた。でもっていつまでたっても終わらない。
プロセスを見るとメモリが(PrivateWorkingSet)が3GB付近で止まっている。何か怪しい・・
ということで、オプションをつけて再度確認
#jhat -J-verbose:gc java_pid24328.hprof
GCが結構な頻度で実行されている。
#jhat -J-verbose:gc -J-mx6000m -J-ms6000m java_pid24328.hprof
で再実行。さっきよりはもちろん頻度は落ちたが、まだFullGCが出る(そしてFullGC 1回に15秒くらいかかっている)。だんだんFullGCの頻度が上がってきた。。まだ足りないか・・
#jhat -J-verbose:gc -J-mx10000m -J-ms10000m java_pid24328.hprof
Dump file created Wed Feb 12 19:45:24 JST 2014
[GC 2560512K->2161709K(9814016K), 1.7790619 secs]
[GC 4722221K->4292917K(9814016K), 2.2919729 secs]
[GC 6853429K->6801901K(9814016K), 2.9861100 secs]
[Full GC 6801901K->6401515K(9814016K), 27.1854356 secs]
Snapshot read, resolving...
Resolving 56763698 objects...
[Full GC 8962027K->6641624K(9814016K), 29.9023006 secs]
[Full GC 9202136K->6313543K(9814016K), 27.5518345 secs]
Chasing references, expect 11352 dots................................
........................................................................................................................
(ドットが11352個出たのかな)
........................................................................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
で完了した。結構時間かかった。こんなのサーバ上でやれないですね(hprofの出力を絞ればいいのかな)。
3.結果をみる
ブラウザで、http://127.0.0.1:7000/ で見てみる。
これだとよくわからないなぁとおもったので、最後のほうにある「Show heap histogram」をクリックしてみたら、、これまたレスポンスが返ってこない。。(GCが出ているわけでもない)。
10分たってもレスポンスが返ってこないので、、諦めました。やはりでかすぎたのかな。ということで、次回MemoryAnalyzerに期待。
2013年11月30日土曜日
Tomcatとjsvcとumask
前回tomcatをjsvcでサービス化をしてみました(ここ)。で後で気が付いたのですが、実行ユーザのumaskが有効になっていないみたいです。
# ls -lrt /var/tomcat/logs
total 12
-rw------- 1 root root 0 Nov 29 15:14 catalina-daemon.out
-rw------- 1 tomcat tomcat 0 Nov 29 15:14 manager.2013-11-29.log
-rw------- 1 tomcat tomcat 0 Nov 29 15:14 host-manager.2013-11-29.log
-rw-r--r-- 1 tomcat tomcat 0 Nov 29 15:14 localhost_access_log.2013-11-29.txt
-rw------- 1 tomcat tomcat 447 Nov 29 15:14 localhost.2013-11-29.log
-rw------- 1 tomcat tomcat 2016 Nov 29 15:14 catalina.2013-11-29.log
-rw------- 1 root root 2016 Nov 29 15:14 catalina-daemon.err
アクセスログだけumask 0022が聞いているみたいです。これだと何かと都合が悪いので、
指定できないか?を調べてみたのですが、helpを見てもそのような記載がありませんでした。
ということで、jsvcのオプションで指定してみます。
# vi /var/tomcat/bin/setenv.sh
====
・
・
#jsvc options
export JSVC_OPTS="-umask 0022"
# ls -lrt /var/tomcat/logs
total 12
-rw------- 1 root root 0 Nov 29 15:14 catalina-daemon.out
-rw------- 1 tomcat tomcat 0 Nov 29 15:14 manager.2013-11-29.log
-rw------- 1 tomcat tomcat 0 Nov 29 15:14 host-manager.2013-11-29.log
-rw-r--r-- 1 tomcat tomcat 0 Nov 29 15:14 localhost_access_log.2013-11-29.txt
-rw------- 1 tomcat tomcat 447 Nov 29 15:14 localhost.2013-11-29.log
-rw------- 1 tomcat tomcat 2016 Nov 29 15:14 catalina.2013-11-29.log
-rw------- 1 root root 2016 Nov 29 15:14 catalina-daemon.err
アクセスログだけumask 0022が聞いているみたいです。これだと何かと都合が悪いので、
指定できないか?を調べてみたのですが、helpを見てもそのような記載がありませんでした。
そこでjsvcのソースを見たところ、"-umask"というオプションで指定できることがわかりました。
ということで、jsvcのオプションで指定してみます。
# vi /var/tomcat/bin/setenv.sh
====
・
・
#jsvc options
export JSVC_OPTS="-umask 0022"
・
・
・
====
これでサービス再起動!
# service tomcat stop
# rm -f /var/tomcat/logs/*
# service tomcat start
# ls -lrt /var/tomcat/logs
-rw-r--r-- 1 tomcat tomcat 0 Nov 29 15:17 manager.2013-11-29.log
-rw-r--r-- 1 tomcat tomcat 0 Nov 29 15:17 host-manager.2013-11-29.log
-rw-r--r-- 1 tomcat tomcat 0 Nov 29 15:17 localhost_access_log.2013-11-29.txt
-rw-r--r-- 1 root root 332 Nov 29 15:41 catalina-daemon.out
-rw-r--r-- 1 tomcat tomcat 1122 Nov 29 15:41 localhost.2013-11-29.log
-rw-r--r-- 1 tomcat tomcat 4828 Nov 29 15:41 catalina.2013-11-29.log
-rw-r--r-- 1 root root 4828 Nov 29 15:41 catalina-daemon.err
めでたし!
2013年11月22日金曜日
Tomcatのサービス化でjsvcを使ってみる
Tomcatのサービス化で、プロセスを活かしたままログローテーションを実装するため、jsvcを使ってみた。環境は以下の通り。
OS:CentOS 6.4(x64)
Java 1.7.0_45
Tomcat 7.0.47
実行ユーザ tomcat
1.JavaとTomcatのセットアップ
それぞれを以下のディレクトリにインストール
・/opt/java/jdk1.7.0_45
・/opt/tomcat/apache-tomcat-7.0.47
実際には以下の通り。まずはjavaのインストール。
# mkdir /opt/java
# cd /opt/java
javaはこちらのサイトから、tarball(jdk-7u45-linux-x64.gz)のものをダウンロードし、/opt/javaに配置
※wgetでは直接ダウンロードできません(304で飛ばされる)
# gunzip jdk-7u45-linux-x64.gz
# tar xvf jdk-7u45-linux-x64
次にtomcatです。
# make /opt/tomcat
# cd /opt/tomcat
# wget http://ftp.jaist.ac.jp/pub/apache/tomcat/tomcat-7/v7.0.47/bin/apache-tomcat-7.0.47.tar.gz
# tar xvfz apache-tomcat-7.0.47.tar.gz
実行アカウントを作成し、上記のtomcatフォルダのオーナーを変更しておく
# useradd -d /opt/tomcat -s /sbin/nologin tomcat
# chown -R tomcat. /opt/tomcat
あと何かと面倒なので、環境変数も設定しておく
# vi ~/.bahsrc
==
export JAVA_HOME=/opt/java/jdk1.7.0_45
export PATH=$PATH:$JAVA_HOME/bin
==
# source ~/.bashrc
# java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
2.jsvcの構築
Tomcatのサイトに記載されいてるようにjsvcを作成してみる。
# cd /opt/tomcat/apache-tomcat-7.0.47/bin
# tar xvfz commons-daemon-native.tar.gz
# cd commons-daemon-1.0.15-native-src/unix
# ./configure
*** Current host ***
checking build system type... x86_64-unknown-linux-gnu
・
・
・
*** Java compilation tools ***
checking for JDK location... configure: error: Java Home not defined. Rerun with --with-java=... parameter
とエラーになってしまった。改めて
# ./configure --with-java=/opt/java/jdk1.7.0_45
*** Current host ***
checking build system type... x86_64-unknown-linux-gnu
と思ってちょっと調べてみたら、、、こんなセキュリティ脆弱性も出ている。
用意するファイルは以下の3つ
・起動スクリプト(例:/etc/init.d/tomcat)
・jsvc起動シェル($CATALINA_HOME/bin/daemon.sh)
・起動引数シェル($CATALINA_BASE/bin/setenv.sh)
上記から順に起動される。
を加えたてみた。
==========================================================
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# -----------------------------------------------------------------------------
# Commons Daemon wrapper script.
#
# $Id: daemon.sh 1202058 2011-11-15 06:37:12Z mturk $
# -----------------------------------------------------------------------------
#
# resolve links - $0 may be a softlink
ARG0="$0"
while [ -h "$ARG0" ]; do
ls=`ls -ld "$ARG0"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
ARG0="$link"
else
ARG0="`dirname $ARG0`/$link"
fi
done
DIRNAME="`dirname $ARG0`"
PROGRAM="`basename $ARG0`"
while [ ".$1" != . ]
do
case "$1" in
--java-home )
JAVA_HOME="$2"
shift; shift;
continue
;;
--catalina-home )
CATALINA_HOME="$2"
shift; shift;
continue
;;
--catalina-base )
CATALINA_BASE="$2"
shift; shift;
continue
;;
--catalina-pid )
CATALINA_PID="$2"
shift; shift;
continue
;;
--tomcat-user )
TOMCAT_USER="$2"
shift; shift;
continue
;;
--service-start-wait-time )
SERVICE_START_WAIT_TIME="$2"
shift; shift;
continue
;;
* )
break
;;
esac
done
# OS specific support (must be 'true' or 'false').
cygwin=false;
darwin=false;
case "`uname`" in
CYGWIN*)
cygwin=true
;;
Darwin*)
darwin=true
;;
esac
# Use the maximum available, or set MAX_FD != -1 to use that
test ".$MAX_FD" = . && MAX_FD="maximum"
# Setup parameters for running the jsvc
#
test ".$TOMCAT_USER" = . && TOMCAT_USER=tomcat
# Set JAVA_HOME to working JDK or JRE
# JAVA_HOME=/opt/jdk-1.6.0.22
# If not set we'll try to guess the JAVA_HOME
# from java binary if on the PATH
#
if [ -z "$JAVA_HOME" ]; then
JAVA_BIN="`which java 2>/dev/null || type java 2>&1`"
test -x "$JAVA_BIN" && JAVA_HOME="`dirname $JAVA_BIN`"
test ".$JAVA_HOME" != . && JAVA_HOME=`cd "$JAVA_HOME/.." >/dev/null; pwd`
else
JAVA_BIN="$JAVA_HOME/bin/java"
fi
# Only set CATALINA_HOME if not already set
test ".$CATALINA_HOME" = . && CATALINA_HOME=`cd "$DIRNAME/.." >/dev/null; pwd`
test ".$CATALINA_BASE" = . && CATALINA_BASE="$CATALINA_HOME"
test ".$CATALINA_MAIN" = . && CATALINA_MAIN=org.apache.catalina.startup.Bootstrap
# If not explicitly set, look for jsvc in CATALINA_BASE first then CATALINA_HOME
if [ -z $JSVC ]; then
JSVC="$CATALINA_BASE/bin/jsvc"
if [ ! -x $JSVC ]; then
JSVC="$CATALINA_HOME/bin/jsvc"
fi
fi
# Set the default service-start wait time if necessary
test ".$SERVICE_START_WAIT_TIME" = . && SERVICE_START_WAIT_TIME=10
# Ensure that any user defined CLASSPATH variables are not used on startup,
# but allow them to be specified in setenv.sh, in rare case when it is needed.
CLASSPATH=
JAVA_OPTS=
if [ -r "$CATALINA_BASE/bin/setenv.sh" ]; then
. "$CATALINA_BASE/bin/setenv.sh"
elif [ -r "$CATALINA_HOME/bin/setenv.sh" ]; then
. "$CATALINA_HOME/bin/setenv.sh"
fi
# Add on extra jar files to CLASSPATH
test ".$CLASSPATH" != . && CLASSPATH="${CLASSPATH}:"
CLASSPATH="$CLASSPATH$CATALINA_HOME/bin/bootstrap.jar:$CATALINA_HOME/bin/commons-daemon.jar"
test ".$CATALINA_OUT" = . && CATALINA_OUT="$CATALINA_BASE/logs/catalina-daemon.out"
test ".$CATALINA_TMP" = . && CATALINA_TMP="$CATALINA_BASE/temp"
# added by hayashi 2013/11/16
test ".$CATALINA_ERR" = . && CATALINA_ERR="$CATALINA_BASE/logs/catalina-daemon.out"
# Add tomcat-juli.jar to classpath
# tomcat-juli.jar can be over-ridden per instance
if [ -r "$CATALINA_BASE/bin/tomcat-juli.jar" ] ; then
CLASSPATH="$CLASSPATH:$CATALINA_BASE/bin/tomcat-juli.jar"
else
CLASSPATH="$CLASSPATH:$CATALINA_HOME/bin/tomcat-juli.jar"
fi
# Set juli LogManager config file if it is present and an override has not been issued
if [ -z "$LOGGING_CONFIG" ]; then
if [ -r "$CATALINA_BASE/conf/logging.properties" ]; then
LOGGING_CONFIG="-Djava.util.logging.config.file=$CATALINA_BASE/conf/logging.properties"
else
# Bugzilla 45585
LOGGING_CONFIG="-Dnop"
fi
fi
test ".$LOGGING_MANAGER" = . && LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"
JAVA_OPTS="$JAVA_OPTS $LOGGING_MANAGER"
# Set -pidfile
test ".$CATALINA_PID" = . && CATALINA_PID="$CATALINA_BASE/logs/catalina-daemon.pid"
# Increase the maximum file descriptors if we can
if [ "$cygwin" = "false" ]; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ "$?" -eq 0 ]; then
# Darwin does not allow RLIMIT_INFINITY on file soft limit
if [ "$darwin" = "true" -a "$MAX_FD_LIMIT" = "unlimited" ]; then
MAX_FD_LIMIT=`/usr/sbin/sysctl -n kern.maxfilesperproc`
fi
test ".$MAX_FD" = ".maximum" && MAX_FD="$MAX_FD_LIMIT"
ulimit -n $MAX_FD
if [ "$?" -ne 0 ]; then
echo "$PROGRAM: Could not set maximum file descriptor limit: $MAX_FD"
fi
else
echo "$PROGRAM: Could not query system maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# ----- Execute The Requested Command -----------------------------------------
case "$1" in
run )
shift
"$JSVC" $* \
$JSVC_OPTS \
-java-home "$JAVA_HOME" \
-pidfile "$CATALINA_PID" \
-wait "$SERVICE_START_WAIT_TIME" \
-nodetach \
-outfile "&1" \
-errfile "&2" \
-classpath "$CLASSPATH" \
"$LOGGING_CONFIG" $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" \
-Dcatalina.base="$CATALINA_BASE" \
-Dcatalina.home="$CATALINA_HOME" \
-Djava.io.tmpdir="$CATALINA_TMP" \
$CATALINA_MAIN
exit $?
;;
start )
"$JSVC" $JSVC_OPTS \
-java-home "$JAVA_HOME" \
-user $TOMCAT_USER \
-pidfile "$CATALINA_PID" \
-wait "$SERVICE_START_WAIT_TIME" \
-outfile "$CATALINA_OUT" \
-errfile "$CATALINA_ERR" \
-classpath "$CLASSPATH" \
"$LOGGING_CONFIG" $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" \
-Dcatalina.base="$CATALINA_BASE" \
-Dcatalina.home="$CATALINA_HOME" \
-Djava.io.tmpdir="$CATALINA_TMP" \
$CATALINA_MAIN
exit $?
;;
stop )
"$JSVC" $JSVC_OPTS \
-stop \
-pidfile "$CATALINA_PID" \
-classpath "$CLASSPATH" \
-Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" \
-Dcatalina.base="$CATALINA_BASE" \
-Dcatalina.home="$CATALINA_HOME" \
-Djava.io.tmpdir="$CATALINA_TMP" \
$CATALINA_MAIN
exit $?
;;
version )
"$JSVC" \
-java-home "$JAVA_HOME" \
-pidfile "$CATALINA_PID" \
-classpath "$CLASSPATH" \
-errfile "&2" \
-version \
-check \
$CATALINA_MAIN
if [ "$?" = 0 ]; then
"$JAVA_BIN" \
-classpath "$CATALINA_HOME/lib/catalina.jar" \
org.apache.catalina.util.ServerInfo
fi
exit $?
;;
* )
echo "Unknown command: \`$1'"
echo "Usage: $PROGRAM ( commands ... )"
echo "commands:"
echo " run Start Tomcat without detaching from console"
echo " start Start Tomcat"
echo " stop Stop Tomcat"
echo " version What version of commons daemon and Tomcat"
echo " are you running?"
exit 1
;;
esac
#Use the value '&2' to simulate '1>&2'
export CATALINA_OUT=
#stderr (defaults to $CATALINA_BASE/logs/catalina-daemon.out)
#Use the value '&1' to simulate '2>&1'
export CATALINA_ERR=
#java.io.tmpdir (defaults to $CATALINA_BASE/temp)
export CATALINA_TMP=
#wait waittime seconds for the service to start
#waittime should multiple of 10 (min=10)
export SERVICE_START_WAIT_TIME=10
#jsvc options
export JSVC_OPTS=
#jsvc verbosely print debugging information
#export JSVC_OPTS="$JSVC_OPTS -debug"
# jsvc working directory
export JSVC_OPTS="$JSVC_OPTS -cwd $CATALINA_BASE"
export JAVA_OPTS=" \
-server \
-DTOMCATID=tomcat \
-verbose:gc \
-Xms256m -Xmx256m \
-XX:PermSize=64m -XX:MaxPermSize=128m \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:+PrintGCDetails \
-XX:+PrintGCTimeStamps
export CLASSPATH=
export CATALINA_OPTS=
※ポイントは、gcログ出力は指定せず、標準出力に出すようにしておくこと。ファイル指定すると
gcログはjsvcのreopenが効かなくて困る。
あとはjsvcはなんとなくbinディレクトにコピーしておく(パス名長いし、実行モジュールは一か所に)。
# service tomcat start
で実行してみる。エラーになったり、成功したり。調べてみると、Tomcatが起動完了するまでの
時間が10秒以上かかることがあり、その際にtimeoutとなっていたみたい。ただしそれでもtomcat
は起動しているようですが。。いずれにしてもエラーは気持ち悪いので、setenv.shの中の
SERVICE_START_WAIT_TIMEを60(1分)にすることで、エラーは解消された。
ちなみに起動後のプロセスを見るとこんな感じ
# ps -ef|grep jsv[c]
root 2437 1 0 16:19 ? 00:00:00 jsvc.exec -cwd /var/tomcat -java-home /opt/java/jdk1.7.0_45 -user tomcat -pidfile /var/run/tomcat -wait 60 -outfile /var/tomcat/logs/catalina-daemon.out -errfile /var/tomcat/logs/catalina-daemon.err -classpath /opt/tomcat/apache-tomcat-7.0.47/bin/bootstrap.jar:/opt/tomcat/apache-tomcat-7.0.47/bin/commons-daemon.jar:/opt/tomcat/apache-tomcat-7.0.47/bin/tomcat-juli.jar -Djava.util.logging.config.file=/var/tomcat/conf/logging.properties -server -DTOMCATID=tomcat -verbose:gc -Xms256m -Xmx256m -XX:PermSize=64m -XX:MaxPermSize=128m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/var/tomcat/6/drpcbase/logs/gc.log -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs= -Dcatalina.base=/var/tomcat -Dcatalina.home=/opt/tomcat/apache-tomcat-7.0.47 -Djava.io.tmpdir=/var/tomcat/temp org.apache.catalina.startup.Bootstrap
tomcat 2438 2437 4 16:19 ? 00:00:03 jsvc.exec -cwd /var/tomcat -java-home /opt/java/jdk1.7.0_45 -user tomcat -pidfile /var/run/tomcat -wait 60 -outfile /var/tomcat/logs/catalina-daemon.out -errfile /var/tomcat/logs/catalina-daemon.err -classpath /opt/tomcat/apache-tomcat-7.0.47/bin/bootstrap.jar:/opt/tomcat/apache-tomcat-7.0.47/bin/commons-daemon.jar:/opt/tomcat/apache-tomcat-7.0.47/bin/tomcat-juli.jar -Djava.util.logging.config.file=/var/tomcat/conf/logging.properties -server -DTOMCATID=tomcat -verbose:gc -Xms256m -Xmx256m -XX:PermSize=64m -XX:MaxPermSize=128m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/var/tomcat/6/drpcbase/logs/gc.log -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs= -Dcatalina.base=/var/tomcat -Dcatalina.home=/opt/tomcat/apache-tomcat-7.0.47 -Djava.io.tmpdir=/var/tomcat/temp org.apache.catalina.startup.Bootstrap
5.ログローテーション
まず現状のファイルアクセスを確認してみる。
# lsof |grep jsvc|grep catalina-daemon
jsvc 2437 root 1w REG 253,0 13923 17039949 /var/tomcat/logs/catalina-daemon.out
jsvc 2437 root 2w REG 253,0 2016 17040504 /var/tomcat/logs/catalina-daemon.err
jsvc 2438 tomcat 1w REG 253,0 13923 17039949 /var/tomcat/logs/catalina-daemon.out
jsvc 2438 tomcat 2w REG 253,0 2016 17040504 /var/tomcat/logs/catalina-daemon.err
# service tomcat reopen
# lsof |grep jsvc|grep catalina-daemon
jsvc 2437 root 1w REG 253,0 13923 17039949 /var/tomcat/logs/old/catalina-daemon.out
jsvc 2437 root 2w REG 253,0 2016 17040504 /var/tomcat/logs/old/catalina-daemon.err
jsvc 2438 tomcat 1w REG 253,0 0 17040554 /var/tomcat/logs/catalina-daemon.out
jsvc 2438 tomcat 2w REG 253,0 0 17040557 /var/tomcat/logs/catalina-daemon.err
ん?子プロセスは無事切り替わりましたが、、親プロセスがまだold配下をopenしっぱなしですね。
ということで、Tomcatに標準出力、標準エラー出力をするアプリを仕込んで出力してみたところ、
親プロセスがオープンしているログ(old配下)には何も出力されていませんが、子プロセスのほう
にはきっちり出力されていました(OutOfMemoryも発生させて同様でした)。
という意味では、あまり弊害はなさそうですが、、、(jsvcプロセス自体が何か出力する際に使われるのか??)なぞは調べが付かなかった。。。また今度。
(2014/2/15)
別件でもう少し調べてみたところ、、標準出力以外のtomcatのログ(アクセスログとか)は切替わっていないようでした。
# lsof |grep 31141|grep logs
jsvc 31141 tomcat 1w REG 253,2 774 2621517 /var/tomcat/logs/catalina.out
jsvc 31141 tomcat 2w REG 253,2 774 2621517 /var/tomcat/logs/catalina.out
jsvc 31141 tomcat 11w REG 253,2 3850 2621505 /var/tomcat/logs/catalina.2014-02-15.log (deleted)
jsvc 31141 tomcat 12w REG 253,2 240 2621514 /var/tomcat/logs/localhost.2014-02-15.log (deleted)
jsvc 31141 tomcat 13w REG 253,2 0 2621515 /var/tomcat/logs/manager.2014-02-15.log (deleted)
jsvc 31141 tomcat 14w REG 253,2 0 2621516 /var/tomcat/logs/host-manager.2014-02-15.log (deleted)
jsvc 31141 tomcat 63w REG 253,2 410 2621520 /var/tomcat/logs/localhost_access_log.2014-02-15.txt (deleted)
OS:CentOS 6.4(x64)
Java 1.7.0_45
Tomcat 7.0.47
実行ユーザ tomcat
1.JavaとTomcatのセットアップ
それぞれを以下のディレクトリにインストール
・/opt/java/jdk1.7.0_45
・/opt/tomcat/apache-tomcat-7.0.47
実際には以下の通り。まずはjavaのインストール。
# mkdir /opt/java
# cd /opt/java
javaはこちらのサイトから、tarball(jdk-7u45-linux-x64.gz)のものをダウンロードし、/opt/javaに配置
※wgetでは直接ダウンロードできません(304で飛ばされる)
# gunzip jdk-7u45-linux-x64.gz
# tar xvf jdk-7u45-linux-x64
次にtomcatです。
# make /opt/tomcat
# cd /opt/tomcat
# wget http://ftp.jaist.ac.jp/pub/apache/tomcat/tomcat-7/v7.0.47/bin/apache-tomcat-7.0.47.tar.gz
# tar xvfz apache-tomcat-7.0.47.tar.gz
実行アカウントを作成し、上記のtomcatフォルダのオーナーを変更しておく
# useradd -d /opt/tomcat -s /sbin/nologin tomcat
# chown -R tomcat. /opt/tomcat
あと何かと面倒なので、環境変数も設定しておく
# vi ~/.bahsrc
==
export JAVA_HOME=/opt/java/jdk1.7.0_45
export PATH=$PATH:$JAVA_HOME/bin
==
# source ~/.bashrc
# java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
Tomcatのサイトに記載されいてるようにjsvcを作成してみる。
# cd /opt/tomcat/apache-tomcat-7.0.47/bin
# tar xvfz commons-daemon-native.tar.gz
# cd commons-daemon-1.0.15-native-src/unix
# ./configure
*** Current host ***
checking build system type... x86_64-unknown-linux-gnu
・
・
・
*** Java compilation tools ***
checking for JDK location... configure: error: Java Home not defined. Rerun with --with-java=... parameter
とエラーになってしまった。改めて
# ./configure --with-java=/opt/java/jdk1.7.0_45
*** Current host ***
checking build system type... x86_64-unknown-linux-gnu
・
configure: WARNING: cannot find headers for libcap
・
configure: WARNING: cannot find headers for libcap
・
*** All done ***
Now you can issue "make"
となった。makeできるらしいが、libcapのヘッダーがないってワーニングがでている。これは
Capablityが使えないということになるのかな?そうなると起動時のユーザを変更できないと思われる。とりあえず、対応なしで進めてみる。
Capablityが使えないということになるのかな?そうなると起動時のユーザを変更できないと思われる。とりあえず、対応なしで進めてみる。
と思ってちょっと調べてみたら、、、こんなセキュリティ脆弱性も出ている。
うーん、今回はVersion的には解決していますが、こういった類の問題が今後も出る可能性が
あるという点では、jsvcを使わずに、普通にtomcatをsuで実行したほうがよいのかもしれない。
必要はよくよく検討したほうがよいというか。
ちなみにNational Vulnerability Databaseでjsvcの脆弱性はこれだけしかヒットしなかった。
とりあえず今回はjsvcを使う想定で進める。
# make
(cd native; make all)
make[1]: Entering directory `/opt/tomcat/apache-tomcat-7.0.47/bin/commons-daemon-1.0.15-native-src/unix/native'
gcc -g -O2 -DOS_LINUX -DDSO_DLFCN -DCPU=\"amd64\" -Wall -Wstrict-prototypes -I/opt/java/jdk1.7.0_45/include -I/opt/java/jdk1.7.0_45/include/linux -c jsvc-unix.c -o jsvc-unix.o
・
・
・
gcc jsvc-unix.o libservice.a -ldl -lpthread -o ../jsvc
make[1]: Leaving directory `/opt/tomcat/apache-tomcat-7.0.47/bin/commons-daemon-1.0.15-native-src/unix/native'
# ./jsvc --help
Usage: jsvc [-options] class [args...]
・
・
・
jsvc (Apache Commons Daemon) 1.0.15-dev
Copyright (c) 1999-2013 Apache Software Foundation.
ということで、Version情報も確認でき、コンパイル完了。
3.起動スクリプトの設定
用意するファイルは以下の3つ
・起動スクリプト(例:/etc/init.d/tomcat)
・jsvc起動シェル($CATALINA_HOME/bin/daemon.sh)
・起動引数シェル($CATALINA_BASE/bin/setenv.sh)
上記から順に起動される。
/etc/init.d/tomcat
起動スクリプトを用意。ポイントは、複数のTomcatを起動できるように
・固有になるインスタンス名を設定
・CATALINA_BASEに、/var/[インスタンス名]を設定
としたこと。
==========================================================
#!/bin/sh
#
# tomcat Startup script for the Apache Tomcat Servlet/JSP container.
#
# chkconfig: - 80 10
# description: The Apache Tomcat Servlet/JSP container.
#
# Source function library.
. /etc/init.d/functions
RETVAL=0
INSTANCE=tomcat
JAVA_HOME=/opt/java/jdk1.7.0_45
CATALINA_HOME=/opt/tomcat/apache-tomcat-7.0.47
DAEMON=$CATALINA_HOME/bin/daemon.sh
USER=tomcat
shellname=${0##*/}
CATALINA_BASE=/var/$INSTANCE
LOCKFILE=/var/lock/subsys/$shellname
PIDFILE=/var/run/$shellname
start() {
echo -n $"Starting tomcat: "
$DAEMON --java-home $JAVA_HOME \
--catalina-home $CATALINA_HOME \
--catalina-base $CATALINA_BASE \
--catalina-pid $PIDFILE \
--tomcat-user $USER \
start
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
echo_success
touch $LOCKFILE
else
echo failure
fi
echo
return $RETVAL
}
stop() {
echo -n $"Shutting down tomcat: "
local PID=`cat $PIDFILE`
if [ -z "$PID" ] ; then
echo "server is not running "
return 0
fi
$DAEMON --java-home $JAVA_HOME \
--catalina-home $CATALINA_HOME \
--catalina-base $CATALINA_BASE \
--catalina-pid $PIDFILE \
stop
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
echo_success
rm -f $LOCKFILE
else
echo failure
fi
echo
return $RETVAL
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status -p $PIDFILE jsvc
;;
reopen)
kill -USR1 `cat $PIDFILE` > /dev/null 2>&1 || true
;;
*)
echo $"Usage: $0 {start|stop|restart|status|reopen}"
exit 3
esac
==========================================================
起動スクリプトを用意。ポイントは、複数のTomcatを起動できるように
・固有になるインスタンス名を設定
・CATALINA_BASEに、/var/[インスタンス名]を設定
としたこと。
==========================================================
#!/bin/sh
#
# tomcat Startup script for the Apache Tomcat Servlet/JSP container.
#
# chkconfig: - 80 10
# description: The Apache Tomcat Servlet/JSP container.
#
# Source function library.
. /etc/init.d/functions
RETVAL=0
INSTANCE=tomcat
JAVA_HOME=/opt/java/jdk1.7.0_45
CATALINA_HOME=/opt/tomcat/apache-tomcat-7.0.47
DAEMON=$CATALINA_HOME/bin/daemon.sh
USER=tomcat
shellname=${0##*/}
CATALINA_BASE=/var/$INSTANCE
LOCKFILE=/var/lock/subsys/$shellname
PIDFILE=/var/run/$shellname
start() {
echo -n $"Starting tomcat: "
$DAEMON --java-home $JAVA_HOME \
--catalina-home $CATALINA_HOME \
--catalina-base $CATALINA_BASE \
--catalina-pid $PIDFILE \
--tomcat-user $USER \
start
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
echo_success
touch $LOCKFILE
else
echo failure
fi
echo
return $RETVAL
}
stop() {
echo -n $"Shutting down tomcat: "
local PID=`cat $PIDFILE`
if [ -z "$PID" ] ; then
echo "server is not running "
return 0
fi
$DAEMON --java-home $JAVA_HOME \
--catalina-home $CATALINA_HOME \
--catalina-base $CATALINA_BASE \
--catalina-pid $PIDFILE \
stop
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
echo_success
rm -f $LOCKFILE
else
echo failure
fi
echo
return $RETVAL
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status -p $PIDFILE jsvc
;;
reopen)
kill -USR1 `cat $PIDFILE` > /dev/null 2>&1 || true
;;
*)
echo $"Usage: $0 {start|stop|restart|status|reopen}"
exit 3
esac
==========================================================
$CATALINA_HOME/bin/daemon.sh
次にjsvc起動シェルを用意する。binディレクトリに、オリジナルのdaemon.shがあるので、それをベースに気になるところを修正。
具体的にはstart処理のerrfileの出力先が標準出力になっていたので、選択ができるように修正を加えたてみた。
==========================================================
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# -----------------------------------------------------------------------------
# Commons Daemon wrapper script.
#
# $Id: daemon.sh 1202058 2011-11-15 06:37:12Z mturk $
# -----------------------------------------------------------------------------
#
# resolve links - $0 may be a softlink
ARG0="$0"
while [ -h "$ARG0" ]; do
ls=`ls -ld "$ARG0"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
ARG0="$link"
else
ARG0="`dirname $ARG0`/$link"
fi
done
DIRNAME="`dirname $ARG0`"
PROGRAM="`basename $ARG0`"
while [ ".$1" != . ]
do
case "$1" in
--java-home )
JAVA_HOME="$2"
shift; shift;
continue
;;
--catalina-home )
CATALINA_HOME="$2"
shift; shift;
continue
;;
--catalina-base )
CATALINA_BASE="$2"
shift; shift;
continue
;;
--catalina-pid )
CATALINA_PID="$2"
shift; shift;
continue
;;
--tomcat-user )
TOMCAT_USER="$2"
shift; shift;
continue
;;
--service-start-wait-time )
SERVICE_START_WAIT_TIME="$2"
shift; shift;
continue
;;
* )
break
;;
esac
done
# OS specific support (must be 'true' or 'false').
cygwin=false;
darwin=false;
case "`uname`" in
CYGWIN*)
cygwin=true
;;
Darwin*)
darwin=true
;;
esac
# Use the maximum available, or set MAX_FD != -1 to use that
test ".$MAX_FD" = . && MAX_FD="maximum"
# Setup parameters for running the jsvc
#
test ".$TOMCAT_USER" = . && TOMCAT_USER=tomcat
# Set JAVA_HOME to working JDK or JRE
# JAVA_HOME=/opt/jdk-1.6.0.22
# If not set we'll try to guess the JAVA_HOME
# from java binary if on the PATH
#
if [ -z "$JAVA_HOME" ]; then
JAVA_BIN="`which java 2>/dev/null || type java 2>&1`"
test -x "$JAVA_BIN" && JAVA_HOME="`dirname $JAVA_BIN`"
test ".$JAVA_HOME" != . && JAVA_HOME=`cd "$JAVA_HOME/.." >/dev/null; pwd`
else
JAVA_BIN="$JAVA_HOME/bin/java"
fi
# Only set CATALINA_HOME if not already set
test ".$CATALINA_HOME" = . && CATALINA_HOME=`cd "$DIRNAME/.." >/dev/null; pwd`
test ".$CATALINA_BASE" = . && CATALINA_BASE="$CATALINA_HOME"
test ".$CATALINA_MAIN" = . && CATALINA_MAIN=org.apache.catalina.startup.Bootstrap
# If not explicitly set, look for jsvc in CATALINA_BASE first then CATALINA_HOME
if [ -z $JSVC ]; then
JSVC="$CATALINA_BASE/bin/jsvc"
if [ ! -x $JSVC ]; then
JSVC="$CATALINA_HOME/bin/jsvc"
fi
fi
# Set the default service-start wait time if necessary
test ".$SERVICE_START_WAIT_TIME" = . && SERVICE_START_WAIT_TIME=10
# Ensure that any user defined CLASSPATH variables are not used on startup,
# but allow them to be specified in setenv.sh, in rare case when it is needed.
CLASSPATH=
JAVA_OPTS=
if [ -r "$CATALINA_BASE/bin/setenv.sh" ]; then
. "$CATALINA_BASE/bin/setenv.sh"
elif [ -r "$CATALINA_HOME/bin/setenv.sh" ]; then
. "$CATALINA_HOME/bin/setenv.sh"
fi
# Add on extra jar files to CLASSPATH
test ".$CLASSPATH" != . && CLASSPATH="${CLASSPATH}:"
CLASSPATH="$CLASSPATH$CATALINA_HOME/bin/bootstrap.jar:$CATALINA_HOME/bin/commons-daemon.jar"
test ".$CATALINA_OUT" = . && CATALINA_OUT="$CATALINA_BASE/logs/catalina-daemon.out"
test ".$CATALINA_TMP" = . && CATALINA_TMP="$CATALINA_BASE/temp"
# added by hayashi 2013/11/16
test ".$CATALINA_ERR" = . && CATALINA_ERR="$CATALINA_BASE/logs/catalina-daemon.out"
# Add tomcat-juli.jar to classpath
# tomcat-juli.jar can be over-ridden per instance
if [ -r "$CATALINA_BASE/bin/tomcat-juli.jar" ] ; then
CLASSPATH="$CLASSPATH:$CATALINA_BASE/bin/tomcat-juli.jar"
else
CLASSPATH="$CLASSPATH:$CATALINA_HOME/bin/tomcat-juli.jar"
fi
# Set juli LogManager config file if it is present and an override has not been issued
if [ -z "$LOGGING_CONFIG" ]; then
if [ -r "$CATALINA_BASE/conf/logging.properties" ]; then
LOGGING_CONFIG="-Djava.util.logging.config.file=$CATALINA_BASE/conf/logging.properties"
else
# Bugzilla 45585
LOGGING_CONFIG="-Dnop"
fi
fi
test ".$LOGGING_MANAGER" = . && LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager"
JAVA_OPTS="$JAVA_OPTS $LOGGING_MANAGER"
# Set -pidfile
test ".$CATALINA_PID" = . && CATALINA_PID="$CATALINA_BASE/logs/catalina-daemon.pid"
# Increase the maximum file descriptors if we can
if [ "$cygwin" = "false" ]; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ "$?" -eq 0 ]; then
# Darwin does not allow RLIMIT_INFINITY on file soft limit
if [ "$darwin" = "true" -a "$MAX_FD_LIMIT" = "unlimited" ]; then
MAX_FD_LIMIT=`/usr/sbin/sysctl -n kern.maxfilesperproc`
fi
test ".$MAX_FD" = ".maximum" && MAX_FD="$MAX_FD_LIMIT"
ulimit -n $MAX_FD
if [ "$?" -ne 0 ]; then
echo "$PROGRAM: Could not set maximum file descriptor limit: $MAX_FD"
fi
else
echo "$PROGRAM: Could not query system maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# ----- Execute The Requested Command -----------------------------------------
case "$1" in
run )
shift
"$JSVC" $* \
$JSVC_OPTS \
-java-home "$JAVA_HOME" \
-pidfile "$CATALINA_PID" \
-wait "$SERVICE_START_WAIT_TIME" \
-nodetach \
-outfile "&1" \
-errfile "&2" \
-classpath "$CLASSPATH" \
"$LOGGING_CONFIG" $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" \
-Dcatalina.base="$CATALINA_BASE" \
-Dcatalina.home="$CATALINA_HOME" \
-Djava.io.tmpdir="$CATALINA_TMP" \
$CATALINA_MAIN
exit $?
;;
start )
"$JSVC" $JSVC_OPTS \
-java-home "$JAVA_HOME" \
-user $TOMCAT_USER \
-pidfile "$CATALINA_PID" \
-wait "$SERVICE_START_WAIT_TIME" \
-outfile "$CATALINA_OUT" \
-errfile "$CATALINA_ERR" \
-classpath "$CLASSPATH" \
"$LOGGING_CONFIG" $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" \
-Dcatalina.base="$CATALINA_BASE" \
-Dcatalina.home="$CATALINA_HOME" \
-Djava.io.tmpdir="$CATALINA_TMP" \
$CATALINA_MAIN
exit $?
;;
stop )
"$JSVC" $JSVC_OPTS \
-stop \
-pidfile "$CATALINA_PID" \
-classpath "$CLASSPATH" \
-Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" \
-Dcatalina.base="$CATALINA_BASE" \
-Dcatalina.home="$CATALINA_HOME" \
-Djava.io.tmpdir="$CATALINA_TMP" \
$CATALINA_MAIN
exit $?
;;
version )
"$JSVC" \
-java-home "$JAVA_HOME" \
-pidfile "$CATALINA_PID" \
-classpath "$CLASSPATH" \
-errfile "&2" \
-version \
-check \
$CATALINA_MAIN
if [ "$?" = 0 ]; then
"$JAVA_BIN" \
-classpath "$CATALINA_HOME/lib/catalina.jar" \
org.apache.catalina.util.ServerInfo
fi
exit $?
;;
* )
echo "Unknown command: \`$1'"
echo "Usage: $PROGRAM ( commands ... )"
echo "commands:"
echo " run Start Tomcat without detaching from console"
echo " start Start Tomcat"
echo " stop Stop Tomcat"
echo " version What version of commons daemon and Tomcat"
echo " are you running?"
exit 1
;;
esac
==========================================================
$CATALINA_BASE/bin/setenv.sh
最後に起動引数シェル。ここはjsvcやjavaの引数を記載する。以下例です。
最後に起動引数シェル。ここはjsvcやjavaの引数を記載する。以下例です。
==========================================================
#stdout (defaults to $CATALINA_BASE/logs/catalina-daemon.out)#Use the value '&2' to simulate '1>&2'
export CATALINA_OUT=
#stderr (defaults to $CATALINA_BASE/logs/catalina-daemon.out)
#Use the value '&1' to simulate '2>&1'
export CATALINA_ERR=
#java.io.tmpdir (defaults to $CATALINA_BASE/temp)
export CATALINA_TMP=
#wait waittime seconds for the service to start
#waittime should multiple of 10 (min=10)
export SERVICE_START_WAIT_TIME=10
#jsvc options
export JSVC_OPTS=
#jsvc verbosely print debugging information
#export JSVC_OPTS="$JSVC_OPTS -debug"
export JSVC_OPTS="$JSVC_OPTS -cwd $CATALINA_BASE"
export JAVA_OPTS=" \
-server \
-DTOMCATID=tomcat \
-verbose:gc \
-Xms256m -Xmx256m \
-XX:PermSize=64m -XX:MaxPermSize=128m \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:+PrintGCDetails \
-XX:+PrintGCTimeStamps
export CLASSPATH=
export CATALINA_OPTS=
==========================================================
※ポイントは、gcログ出力は指定せず、標準出力に出すようにしておくこと。ファイル指定すると
gcログはjsvcのreopenが効かなくて困る。
4.起動
# service tomcat start
で実行してみる。エラーになったり、成功したり。調べてみると、Tomcatが起動完了するまでの
時間が10秒以上かかることがあり、その際にtimeoutとなっていたみたい。ただしそれでもtomcat
は起動しているようですが。。いずれにしてもエラーは気持ち悪いので、setenv.shの中の
SERVICE_START_WAIT_TIMEを60(1分)にすることで、エラーは解消された。
ちなみに起動後のプロセスを見るとこんな感じ
# ps -ef|grep jsv[c]
root 2437 1 0 16:19 ? 00:00:00 jsvc.exec -cwd /var/tomcat -java-home /opt/java/jdk1.7.0_45 -user tomcat -pidfile /var/run/tomcat -wait 60 -outfile /var/tomcat/logs/catalina-daemon.out -errfile /var/tomcat/logs/catalina-daemon.err -classpath /opt/tomcat/apache-tomcat-7.0.47/bin/bootstrap.jar:/opt/tomcat/apache-tomcat-7.0.47/bin/commons-daemon.jar:/opt/tomcat/apache-tomcat-7.0.47/bin/tomcat-juli.jar -Djava.util.logging.config.file=/var/tomcat/conf/logging.properties -server -DTOMCATID=tomcat -verbose:gc -Xms256m -Xmx256m -XX:PermSize=64m -XX:MaxPermSize=128m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/var/tomcat/6/drpcbase/logs/gc.log -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs= -Dcatalina.base=/var/tomcat -Dcatalina.home=/opt/tomcat/apache-tomcat-7.0.47 -Djava.io.tmpdir=/var/tomcat/temp org.apache.catalina.startup.Bootstrap
tomcat 2438 2437 4 16:19 ? 00:00:03 jsvc.exec -cwd /var/tomcat -java-home /opt/java/jdk1.7.0_45 -user tomcat -pidfile /var/run/tomcat -wait 60 -outfile /var/tomcat/logs/catalina-daemon.out -errfile /var/tomcat/logs/catalina-daemon.err -classpath /opt/tomcat/apache-tomcat-7.0.47/bin/bootstrap.jar:/opt/tomcat/apache-tomcat-7.0.47/bin/commons-daemon.jar:/opt/tomcat/apache-tomcat-7.0.47/bin/tomcat-juli.jar -Djava.util.logging.config.file=/var/tomcat/conf/logging.properties -server -DTOMCATID=tomcat -verbose:gc -Xms256m -Xmx256m -XX:PermSize=64m -XX:MaxPermSize=128m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/var/tomcat/6/drpcbase/logs/gc.log -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs= -Dcatalina.base=/var/tomcat -Dcatalina.home=/opt/tomcat/apache-tomcat-7.0.47 -Djava.io.tmpdir=/var/tomcat/temp org.apache.catalina.startup.Bootstrap
どうも親プロセスと子プロセスで同じ引数で起動されるみたいですね(今度ソースをみてみよう)。
5.ログローテーション
まず現状のファイルアクセスを確認してみる。
# lsof |grep jsvc|grep catalina-daemon
jsvc 2437 root 1w REG 253,0 13923 17039949 /var/tomcat/logs/catalina-daemon.out
jsvc 2437 root 2w REG 253,0 2016 17040504 /var/tomcat/logs/catalina-daemon.err
jsvc 2438 tomcat 1w REG 253,0 13923 17039949 /var/tomcat/logs/catalina-daemon.out
jsvc 2438 tomcat 2w REG 253,0 2016 17040504 /var/tomcat/logs/catalina-daemon.err
となってます。親プロセスも子プロセスも、catalina-daemon.outとcatalina-daemon.errをopenして
ますね。これを移動してみます。
# mkdir /var/tomcat/logs/old
# mv /var/tomcat/logs/*.* /var/tomcat/logs/old/
# lsof |grep jsvc|grep catalina-daemon
jsvc 2437 root 1w REG 253,0 13923 17039949 /var/tomcat/logs/old/catalina-daemon.out
jsvc 2437 root 2w REG 253,0 2016 17040504 /var/tomcat/logs/old/catalina-daemon.err
jsvc 2438 tomcat 1w REG 253,0 13923 17039949 /var/tomcat/logs/old/catalina-daemon.out
jsvc 2438 tomcat 2w REG 253,0 2016 17040504 /var/tomcat/logs/old/catalina-daemon.err
全てold以下を参照が引っ張られてますね。これでreopenをしてみると、、
# lsof |grep jsvc|grep catalina-daemon
jsvc 2437 root 1w REG 253,0 13923 17039949 /var/tomcat/logs/old/catalina-daemon.out
jsvc 2437 root 2w REG 253,0 2016 17040504 /var/tomcat/logs/old/catalina-daemon.err
jsvc 2438 tomcat 1w REG 253,0 0 17040554 /var/tomcat/logs/catalina-daemon.out
jsvc 2438 tomcat 2w REG 253,0 0 17040557 /var/tomcat/logs/catalina-daemon.err
ん?子プロセスは無事切り替わりましたが、、親プロセスがまだold配下をopenしっぱなしですね。
ということで、Tomcatに標準出力、標準エラー出力をするアプリを仕込んで出力してみたところ、
親プロセスがオープンしているログ(old配下)には何も出力されていませんが、子プロセスのほう
にはきっちり出力されていました(OutOfMemoryも発生させて同様でした)。
という意味では、あまり弊害はなさそうですが、、、(jsvcプロセス自体が何か出力する際に使われるのか??)なぞは調べが付かなかった。。。また今度。
(2014/2/15)
別件でもう少し調べてみたところ、、標準出力以外のtomcatのログ(アクセスログとか)は切替わっていないようでした。
# lsof |grep 31141|grep logs
jsvc 31141 tomcat 1w REG 253,2 774 2621517 /var/tomcat/logs/catalina.out
jsvc 31141 tomcat 2w REG 253,2 774 2621517 /var/tomcat/logs/catalina.out
jsvc 31141 tomcat 11w REG 253,2 3850 2621505 /var/tomcat/logs/catalina.2014-02-15.log (deleted)
jsvc 31141 tomcat 12w REG 253,2 240 2621514 /var/tomcat/logs/localhost.2014-02-15.log (deleted)
jsvc 31141 tomcat 13w REG 253,2 0 2621515 /var/tomcat/logs/manager.2014-02-15.log (deleted)
jsvc 31141 tomcat 14w REG 253,2 0 2621516 /var/tomcat/logs/host-manager.2014-02-15.log (deleted)
jsvc 31141 tomcat 63w REG 253,2 410 2621520 /var/tomcat/logs/localhost_access_log.2014-02-15.txt (deleted)
こんな感じ。標準出力、エラー出力が切り替え対象ってことですかね。まぁ当然と言えば当然か。他のファイルはそもそも日付ベースでローテーションかかってますし、、別で対応すればよいということですかね。
2013年11月4日月曜日
Windows8 Proにvargrantを入れてみる(その2)
前回はvagrantで仮想OSを起動するところまで実施。Hyper-Vとの共存で手こずった。
その後何かと触っていると気になった点を挙げておこう。
・ゲストOSにnetworkを追加してみる
今回ネットワークはデフォルトのフォワード構成を使っているわけですが、フォワードだと何かを
面倒なので、ブリッジモードで通常のネットワークにつながるNICを追加してみる。
1.VirtualBoxのオプション追加
2.Vagrantfileを修正
mitty# cd ~/vagrant/svr11
Installing the 'sahara' plugin. This can take a few minutes...
Installed the plugin 'sahara (0.0.16)'!
2.sandboxを有効にする
sandboxにしたい環境に移動し、on(有効)にする。
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
[default] Sandbox mode is on
3.rollback/commitを試す
・svr11の書き込みをrollback
mitty# vagrant sandbox on
mitty#
成功はしたものの、時間がかかる。suspend/haltしておくと早い。
4.sandboxを無効にする
mitty#
・ゲストOSをsnapshot取得のためのplug-inの「vagrant-vbox-snapshot」を入れてみる。
1.vagrant-vbox-snapshotのインストール
mitty# vagrant plugin install vagrant-vbox-snapshot
Installing the 'vagrant-vbox-snapshot' plugin. This can take a few minutes...
Installed the plugin 'vagrant-vbox-snapshot (0.0.4)'!
2.snapshotを取得してみる
snapshotに名前が付けられるので、「init」という名前で作成してみる。
mitty# vagrant snapshot take init
eがなくなった。戻ったっということだ。ちなみにsnapshot(init)は残ったままだ。
4.snapshotを任意の時点に戻してみる
mitty# vagrant snapshot take modified
Taking snapshot modified
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
mitty# vagrant snapshot list
Listing snapshots for 'default':
Name: init (UUID: ce8054c3-0914-4548-a72b-d929cfda5589)
Name: modified (UUID: 314b3d67-c4e5-4d40-a030-fa6e2f919c6b) *
まずはsnapshot(modified)へリストアしてみる。
mitty# vagrant snapshot go modified
Powering off machine a7c0eae6-677d-4322-a8f5-9c4a1b6f9b22
0%...10%...20%...30%...40%...50%...Restoring snapshot 314b3d67-c4e5-4d40-a030-fa6e2f919c6b
60%...70%...80%...90%...100%
Starting restored VM
[default] Resuming suspended VM...
[default] Booting VM...
mitty# ssh svr11
# ls
a b c d e
fがなくなっており、modifiedの時点まで戻ったことが確認できた。さらに、initの時点まで
戻してみる。
mitty# vagrant snapshot list
Listing snapshots for 'default':
Name: init (UUID: ce8054c3-0914-4548-a72b-d929cfda5589)
Name: modified (UUID: 314b3d67-c4e5-4d40-a030-fa6e2f919c6b) *
その後何かと触っていると気になった点を挙げておこう。
・ゲストOSにnetworkを追加してみる
今回ネットワークはデフォルトのフォワード構成を使っているわけですが、フォワードだと何かを
面倒なので、ブリッジモードで通常のネットワークにつながるNICを追加してみる。
1.VirtualBoxのオプション追加
2.Vagrantfileを修正
mitty# cd ~/vagrant/svr11
mitty# vim Vagrantfile
===
config.vm.network :public_network
===
mitty#
これで起動時にeth1が追加される。DHCP環境であれば、eth1にアサインされたIPでアクセスを
することができる。
(2013/11/16)
IPを固定にするには、以下のように修正すればよいことがわかりました。
===
これでTeraTermでもいけますね。便利。
・作業状態の保存を試みる
vagrantで起動した仮想OSの作業を中断したい時(hibernate)、ゲストOSをsuspendした状態で、
ホストOSの再起動をしてみると、なぜか再起動後にゲストOSが認識できなくなる(VirtualBoxに
は残っているが、vagrantコマンドでは認識しない)。
IPを固定にするには、以下のように修正すればよいことがわかりました。
===
config.vm.network :public_network ,ip: "x.x.x.x"
===
これでTeraTermでもいけますね。便利。
・作業状態の保存を試みる
vagrantで起動した仮想OSの作業を中断したい時(hibernate)、ゲストOSをsuspendした状態で、
ホストOSの再起動をしてみると、なぜか再起動後にゲストOSが認識できなくなる(VirtualBoxに
は残っているが、vagrantコマンドでは認識しない)。
無理やりvagrant upで起動すると新規でゲストOSが起動される。。VirtualBox上に構築されている
OSをvagrantに取り込む方法もわからないため、、再構築するしかない。
(誰か教えてほしい・・)
ちなみにホストOS停止前に、ゲストOSを停止した場合は、今のところ問題はないようです。
これだと作業途中を保存できないんだよな~
(2013/11/06)
取り込む方法がありました。vagrantによって構築したゲストOSだけかもしれませんが、、
svr11が起動できなくなったと想します。
1.ゲストOSのIDを確認
mitty# cd ~/VirtualBox\ VMs/svr11_default_1383543354
mitty# less *.vbox
2.svr11とゲストOSのIDの紐づけ
mitty# cd ~/vagrant/svr11/.vagrant/machines/default/virtualbox
mitty# echo 4c9d39f8-3e2e-4eab-89f3-74c952d624b0 > id
mitty# cd ~/vagrant/svr11/
mitty# vagrant up
起動できれば終了!
・vagrantコマンドのデバッグ
mitty# VAGRANT_LOG=INFO vagrant up
・ゲストOSをある時点までrollbackするためのplug-inの「sahara」を入れてみる。
1.saharaのインストール
mitty# vagrant plugin install sahara
OSをvagrantに取り込む方法もわからないため、、再構築するしかない。
(誰か教えてほしい・・)
ちなみにホストOS停止前に、ゲストOSを停止した場合は、今のところ問題はないようです。
これだと作業途中を保存できないんだよな~
(2013/11/06)
取り込む方法がありました。vagrantによって構築したゲストOSだけかもしれませんが、、
svr11が起動できなくなったと想します。
1.ゲストOSのIDを確認
mitty# cd ~/VirtualBox\ VMs/svr11_default_1383543354
mitty# less *.vbox
<VirtualBox xmlns="http://www.innotek.de/VirtualBox-settings" version="1.12-windows">
<Machine uuid="{4c9d39f8-3e2e-4eab-89f3-74c952d624b0}"
・
・
・
上記のMachineタグのuuid属性の値を確認します。
mitty# cd ~/vagrant/svr11/.vagrant/machines/default/virtualbox
mitty# echo 4c9d39f8-3e2e-4eab-89f3-74c952d624b0 > id
mitty# cd ~/vagrant/svr11/
mitty# vagrant up
起動できれば終了!
・vagrantコマンドのデバッグ
mitty# VAGRANT_LOG=INFO vagrant up
・ゲストOSをある時点までrollbackするためのplug-inの「sahara」を入れてみる。
1.saharaのインストール
mitty# vagrant plugin install sahara
Installing the 'sahara' plugin. This can take a few minutes...
Installed the plugin 'sahara (0.0.16)'!
2.sandboxを有効にする
sandboxにしたい環境に移動し、on(有効)にする。
mitty# cd ~/vagrant/svr11
mitty# vagrant sandbox on
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
mitty# vagrant sandbox status
[default] Sandbox mode is on
3.rollback/commitを試す
・svr11の書き込みをrollback
mitty# cd ~/vagrant/svr11
mitty# ssh svr11
# touch a
# logout
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
mitty#
mitty# ssh svr11
なくなった。成功。ちなみに
mitty# vagrant sandbox status
[default] Sandbox mode is on
・svr12の書き込みをcommit
# touch a
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
mitty# vagrant sandbox rollback
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
mitty#
mitty# ssh svr11
# ls
#
なくなった。成功。ちなみに
mitty# vagrant sandbox status
[default] Sandbox mode is on
sandboxは有効な状態のままでした。
mitty# ssh svr11
# logout
mitty# vagrant sandbox commit
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
4.sandboxを無効にする
mitty# vagrant sandbox off
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
ちなみに変更したのちにcommit/rollbackをしないまま、offにすると、commitされたことになる
ようです。他のサイトではrollbackと書かれていたりしたので、Versionによって動きが異なるかも
しれません(要注意)。
1.vagrant-vbox-snapshotのインストール
mitty# vagrant plugin install vagrant-vbox-snapshot
Installing the 'vagrant-vbox-snapshot' plugin. This can take a few minutes...
Installed the plugin 'vagrant-vbox-snapshot (0.0.4)'!
snapshotに名前が付けられるので、「init」という名前で作成してみる。
mitty# cd ~/vagrant/svr11
Taking snapshot init
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
mitty# vagrant snapshot list
Listing snapshots for 'default':
Name: init (UUID: ce8054c3-0914-4548-a72b-d929cfda5589) *
mitty#
initという名前のスナップショットがあることがわかる。
3.snapshotを戻してみる
最後に取得したsnapshotに戻してみる。
最後に取得したsnapshotに戻してみる。
mitty# ssh svr11
# touch e
# touch e
# logout
mitty# vagrant snapshot back
0%...10%...20%...30%...40%...50%...Restoring snapshot ce8054c3-0914-4548-a72b-d929cfda5589
60%...70%...80%...90%...100%
Starting restored VM
[default] Resuming suspended VM...
[default] Booting VM...
mitty# ssh svr11
# ls
# a b c d
eがなくなった。戻ったっということだ。ちなみにsnapshot(init)は残ったままだ。
4.snapshotを任意の時点に戻してみる
mitty# ssh svr11
# touch e
# touch e
# logout
Taking snapshot modified
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
mitty# vagrant snapshot list
Listing snapshots for 'default':
Name: init (UUID: ce8054c3-0914-4548-a72b-d929cfda5589)
Name: modified (UUID: 314b3d67-c4e5-4d40-a030-fa6e2f919c6b) *
2回目のsnapshot(modified)を取得した。
mitty# ssh svr11
# touch f
mitty# ssh svr11
# touch f
# logout
まずはsnapshot(modified)へリストアしてみる。
mitty# vagrant snapshot go modified
Powering off machine a7c0eae6-677d-4322-a8f5-9c4a1b6f9b22
0%...10%...20%...30%...40%...50%...Restoring snapshot 314b3d67-c4e5-4d40-a030-fa6e2f919c6b
60%...70%...80%...90%...100%
Starting restored VM
[default] Resuming suspended VM...
[default] Booting VM...
mitty# ssh svr11
# ls
a b c d e
# logout
fがなくなっており、modifiedの時点まで戻ったことが確認できた。さらに、initの時点まで
戻してみる。
mitty# vagrant snapshot list
Listing snapshots for 'default':
Name: init (UUID: ce8054c3-0914-4548-a72b-d929cfda5589)
Name: modified (UUID: 314b3d67-c4e5-4d40-a030-fa6e2f919c6b) *
mitty# vagrant snapshot go init
Powering off machine a7c0eae6-677d-4322-a8f5-9c4a1b6f9b22
0%...10%...20%...30%...40%...50%...Restoring snapshot ce8054c3-0914-4548-a72b-d929cfda5589
60%...70%...80%...90%...100%
Starting restored VM
[default] Resuming suspended VM...
[default] Booting VM...
mitty# ssh svr11
# ls
a b c d
chef solo + knife soloはまたの機会に。# ls
a b c d
# logout
おぉー、もどった。
mitty# vagrant snapshot list
Listing snapshots for 'default':
Name: init (UUID: ce8054c3-0914-4548-a72b-d929cfda5589)
Name: modified (UUID: 314b3d67-c4e5-4d40-a030-fa6e2f919c6b) *
mitty# vagrant snapshot go modified
おぉー、もどった。
mitty# vagrant snapshot list
Listing snapshots for 'default':
Name: init (UUID: ce8054c3-0914-4548-a72b-d929cfda5589)
Name: modified (UUID: 314b3d67-c4e5-4d40-a030-fa6e2f919c6b) *
なるほど。modifiedはまだ残ったままですね。
mitty# ssh svr11
# touch g
# touch g
# logout
mitty# vagrant snapshot take modified
Taking snapshot modified2
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
mitty# vagrant snapshot list
Taking snapshot modified2
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
mitty# vagrant snapshot list
Listing snapshots for 'default':
Name: init (UUID: ce8054c3-0914-4548-a72b-d929cfda5589)
Name: modified (UUID: 314b3d67-c4e5-4d40-a030-fa6e2f919c6b)
Name: modified2 (UUID: 031418ce-57a7-4313-ac43-339a7f148d64) *
Powering off machine a7c0eae6-677d-4322-a8f5-9c4a1b6f9b22
0%...10%...20%...30%...40%...50%...Restoring snapshot 314b3d67-c4e5-4d40-a030-fa6e2f919c6b
60%...70%...80%...90%...100%
Starting restored VM
[default] Resuming suspended VM...
[default] Booting VM...
mitty# vagrant snapshot list
Listing snapshots for 'default':
Name: init (UUID: ce8054c3-0914-4548-a72b-d929cfda5589)
Name: modified (UUID: 314b3d67-c4e5-4d40-a030-fa6e2f919c6b) *
Name: modified2 (UUID: 031418ce-57a7-4313-ac43-339a7f148d64)
となった。modifiedのところに*が付いた。これは最新のsnapshotということだろう。
tips:minttyにvimなどのツールを入れよう
vagrantの環境構築をするために作ったminttyで、使い勝手をよくするために、vimとかをインストールする。
mintty# mingw-get update
mintty# mingw-get upgrade
mintty# mingw-get install msys-coreutils msys-man msys-tar msys-gzip msys-wget msys-zip msys-unzip msys-vim
ちなみにインストールできるツールは
mintty# mingw-get list
で確認ができる。以上。
mintty# mingw-get update
mintty# mingw-get upgrade
mintty# mingw-get install msys-coreutils msys-man msys-tar msys-gzip msys-wget msys-zip msys-unzip msys-vim
ちなみにインストールできるツールは
mintty# mingw-get list
で確認ができる。以上。
2013年10月8日火曜日
tips:manページの色を変更する
設定の保存の意味を込めて記載。
CentOS/Redhat環境でmanページの色でblueがデフォルトで使われて非常に見えづらいので、設定変更した。
# vi ~/.bashrc
==
・
export MANPAGER='less -R'
man() {
env \
LESS_TERMCAP_mb=$(printf "\e[1;31m") \
LESS_TERMCAP_md=$(printf "\e[1;36m") \
LESS_TERMCAP_me=$(printf "\e[0m") \
LESS_TERMCAP_se=$(printf "\e[0m") \
LESS_TERMCAP_so=$(printf "\e[1;44;33m") \
LESS_TERMCAP_ue=$(printf "\e[0m") \
LESS_TERMCAP_us=$(printf "\e[1;32m") \
man "$@"
}
CentOS/Redhat環境でmanページの色でblueがデフォルトで使われて非常に見えづらいので、設定変更した。
# vi ~/.bashrc
==
・
・
# User specific aliases and functions
export MANPAGER='less -R'
man() {
env \
LESS_TERMCAP_mb=$(printf "\e[1;31m") \
LESS_TERMCAP_md=$(printf "\e[1;36m") \
LESS_TERMCAP_me=$(printf "\e[0m") \
LESS_TERMCAP_se=$(printf "\e[0m") \
LESS_TERMCAP_so=$(printf "\e[1;44;33m") \
LESS_TERMCAP_ue=$(printf "\e[0m") \
LESS_TERMCAP_us=$(printf "\e[1;32m") \
man "$@"
}
==
# source ~/.bashrc
見やすくなった。
登録:
投稿 (Atom)

