どちらかというとごはん派

主に仕事用のメモブログ。

【cron】LinuxでのCron作成(エラー編)

2008年11月27日 16時13分53秒 | linux bash
私がはまってしまった箇所やCronの設定で失敗している人の現象から
分かる範囲で解決させましょう。

だいたいの方(私も)は、Cronの設定を「crontab -l」で確認しても大丈夫そう。
そしてログを見てもリロードしているっぽい。
そしてCronも起動済みだけど起動しない。という現象なので、
それを前提としたケースを上げてみる。
(つまり、Cronが起動してなかったとかパス間違えとかいうアレゲなエラーは知らないよ。ってことです。はい。)

①環境変数は初期化されてしまうようです。
 実行したいシェルの内部で利用している環境変数をprofileに書き込んでおいたのですが
 (Linux起動時に有効になる環境変数のことです。)
 Cron起動時には設定されていませんでした。
 シェルからjavaを呼んでいる方なんかは、「PATH=:/usr/local/jdk」とかprofileに
 付け加えたと思うんですが、それがCron起動では無効になってしまいます。
 シェルをただ叩くだけなら有効なんですが、
 Cron起動では初期化され「/usr/bin:/bin」位しか設定されていませんので、
 crontab -eで「PATH=:/usr/local/jdk」や、その他自分で設定した環境変数を記述しましょう。
 
 Cron起動時にenvコマンドを設定すると環境変数がどうなっているか確認できますので
 試してみてください。
 
②SHELLの指定してますか?
 crontab -eでSHELLを指定しないと大抵/bin/shが呼ばれてしまうので、
 bashやkchを使用している方などは、きちんと設定してください。
 
③コマンドモードになってませんか?
 起動時刻を過ぎてcronのログファイル(/var/log/cron)を確認したら、
 なんだか実行したっぽいけど、、、でも上手くいかない場合。
 
 Nov 26 12:43:01 server crond[7651]: (testuser) CMD (run-parts /usr/test/test.sh)
 上記のようなログだった場合に、「CMD」と書いてある場合、
 「CMD」以下の()をコマンドとして実行してあります。
 
 そのため、run-partsとかいうコマンドはないからエラーになってしまうのです。
 これで「sh /usr/test/test.sh」とすればうまくいきます。
 
 Cronの設定をググると「run-parts」というのがあったりなかったりするのですが、
 「実行する」という意味らしいので、コマンドエラーになってしまうなら、直に「sh」で実行させてしまいましょう。
 メリットデメリットはありません。
 
④Cannot open /test.log : No such file or directory
 メールをみるとこんなエラーが出ていたりするのですが、コレは①のエラーに近いものです。
 環境変数として「LOG_OUT=/usr/test/logs」とかをprofileで設定していた場合、
 やはり無効になってしまっていて、
 シェル内の「printf "ログ出力します。" >> ${LOG_OUT}/test.log」
 なんかで、「${LOG_OUT}/test.log」が「/usr/test/logs/test.log」と展開されたい場合に「/test.log」と展開されてしまっているわけです。
 それで、test.logなんていうディレクトリはありませんよ。と言ってるわけです。
 
 これもcrontab -eで「LOG_OUT=/usr/test/logs」を付け加えてあげてください。
 
以上です。
ここら辺を再度確認して実行されたら上手くいくのではないでしょうか?
環境変数の初期化なんて知らなかったので、知っていればもっときれいにシェルが組めたのに。。。
と思いますので、きちんと仕組みを理解しましょう。

【cron】LinuxでのCron作成(作成編)

2008年11月27日 15時28分18秒 | linux bash
LinuxでのCronの作成を行います。
私がはまってしまった箇所や意外とCronの設定で失敗している人が多いようなので
(多い割りにエラー解決の資料が少なくて困りました。)
そこら辺の解決になるようなことはエラー編に書いておきます。
エラーやはまってしまった方は「LinuxでのCron作成(エラー編)」を見てください。
こちらでは、作成部分を書いておきます。

◇前提条件◇
 実行したいシェル・・・/usr/test/test.sh
 シェルの実行ユーザ・・testuser

①まず、rootユーザになること。
 su

②rootユーザで、testuserのcronを作成する。
 ◇理由◇
  rootユーザで、rootのcronにtestuserで実行するように設定しても
  上手くいかないことがある。

  testuserで作成するときには、cronの作成権限を渡してあげる必要があるので、
  ちょっとめんどい。

 まずは、viでcron編集をするように以下のコマンドを投げる
 EDITOR=vi; export EDITOR
 デフォルトのエディターをviにするよ。ってこと。
 意外と重要です。これをしないと変なエディターが起動して、何も出来ません。
 
 それでは、以下のコマンドで、実際に作成する。
 crontab -u testuser -e
 (-uはrootでどのユーザのcronを作成するかを宣言し、-eは作成モードっていうこと。ちなみに-lは確認モード。)

③viで書き込む
 viで開いたら、「i」を押下して「挿入モード」にする。
 挿入モードになったら、以下をコピペする。
 -------------------------------------------------------------------------------------------------
 SHELL=/bin/bash
 PATH=/home/testuser/bin
 MAILTO=testuser
 HOME=/
 
 # run-parts
 0 16 * * * /usr/test/test.sh
 -------------------------------------------------------------------------------------------------
 
 コピペしたら「ESCキー」を押下して「ZZ」(保存して終了)を押下して終了します。

④確認してみましょう
 /var/spool/cron配下にtestuserというファイルが出来るので
 catして、上記と同様である旨を確認する。
 パーミッションは500

 cronのログファイル(/var/log/cron)をcatしてみて
 Nov 26 15:21:01 server crond[6417]: (testuser) RELOAD (cron/testuser)
 こんなようなのがでてればOKです。Cronさんが設定ファイルをリロードしてくれました。

 でてなければCronが起動していない可能性があります。ので起動させておきましょう。
 再起動:service crond restart
 起動 :service crond start

これで、私は「0 16 * * *」で設定したので、16時に起動されるのを待って、確認します。

起動時刻になっても起動しない場合は、「/var/spool/mail/testuser」を見て、
届いたメールから、エラーの内容を確認しましょう。



【Linux】javaのアンインストール(RPMで行う)

2008年11月14日 15時32分12秒 | linux bash
Linux コンピュータで RPM が利用できる場合は、RPMでアンインストールを行います。
まずは、Java がインストールされているかどうかを確認します。
Java のインストールに RPM を使用していない場合は、次の手順を実行する必要はありません。
 1. ターミナルウィンドウを開きます。
 2. rootとしてログインします。
 3. rpm -q jdk と入力します。(またはjreなど)
 4. jdk-<バージョン番号>-fcs といった形式のパッケージが検出された場合、
   Java は RPM を使用してインストールされています。

JDK をアンインストールするには、rpm -e jdk-<バージョン番号>-fcs と入力します。

【Tomcat】UnsupportedEncodingExceptionで起動しない

2008年11月05日 15時14分15秒 | linux bash
tomcatのconfディレクトリ内のxmlファイルを開いて
encoding='cp932'になってる箇所があったらutf-8に修正すること

encoding='cp932' → encoding='utf-8'

出ていたエラー-----------------------------------------------------------------
2008/11/05 14:56:28 org.apache.catalina.core.AprLifecycleListener init
情報: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: C:\Tomcat 6.0\bin;.;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\Program Files\PC Connectivity Solution\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program Files\Java\jdk1.6.0_07\bin;C:\Program Files\All-In-One-Eclipse\eclipse\plugins\org.apache.ant_1.6.5\bin;C:\Program Files\doxygen\bin;C:\Program Files\TortoiseSVN\bin
2008/11/05 14:56:29 org.apache.coyote.http11.Http11Protocol init
情報: Coyote HTTP/1.1を http-8080 で初期化します
2008/11/05 14:56:29 org.apache.catalina.startup.Catalina load
情報: Initialization processed in 3445 ms
2008/11/05 14:56:29 org.apache.naming.NamingContext lookup
警告: 参照の解決中に予測しない例外が発生しました
java.io.UnsupportedEncodingException: cp932
at sun.nio.cs.StreamDecoder.forInputStreamReader(StreamDecoder.java:52)
at java.io.InputStreamReader.<init>(InputStreamReader.java:83)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.createReader(XMLEntityScanner.java:1901)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.setEncoding(XMLEntityScanner.java:445)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanXMLDeclOrTextDecl(XMLDocumentFragmentScannerImpl.java:979)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$XMLDeclDriver.next(XMLDocumentScannerImpl.java:808)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:647)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:450)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse

【bash】 「"」、「'」、「`」の違い

2008年11月03日 20時23分30秒 | linux bash
「"」(ダブルクォーテーション)、
「'」(シングルクォーテーション)、
「`」(バッククォーテーション)にも違いがあります。

変数 name に"pwd"という値を設定。
この変数 name をそれぞれで囲みechoを実行する

・「"」ダブルクォーテーションの場合
 $echo "$name"
 pwd
 「"」は変数の中身を表示します。

・「'」シングルクォーテーションの場合
 $echo '$name'
 $name
 「'」は文字列をそのまま表示しています。

・「`」バッククォーテーションの場合
 $echo `$name`
 /usr/local/test
 「`」は変数の中身をコマンドとして実行しています。

【bash】 ステータス

2008年10月31日 17時27分18秒 | linux bash
bash実行時のステータスは以下の2通り

0:正常終了
1:異常終了

設定ファイルで追加することは可能。

取得方法は「$?」で取得

■使用サンプル
 $ if [ "$?" == 1 ];then
 $ echo "異常終了しました。"
 $ fi
 exit 1
 
最後の「exit 1」は、このプログラムをエラーコード1で終わらせる。という意味。
これがないと、bashのファイルは、
続けられる限り処理を進めてしまうので、エラーを検知したら
ちゃんと終わらせましょう。

【bash】 配列のあれこれ

2008年10月21日 23時22分03秒 | linux bash
bashはshellと違って、foreachが使用できないので
もし同じような利用を求める場合には、配列を利用すること

■配列の設定
array=(1 2 3 4 5)

■使用方法
$ for num in ${array[@]};do

$  echo ${num}

$ done

■結果
1
2
3
4
5

■+@として・・
$ array=(a b c d)
$ i=0
$ while [ $count -le 4 ];do
$ echo "${array[i]}"
$ i=`expr $i + 1`
$ done
1
2
3
4
5
これも同様の結果を得る。
配列の要素は0からはじまる(cやjavaと同じ)

■豆知識
①まずは5つの変数に値を設定
str1=A
str2=B
str3=C
str4=D
str5=E

②変数を配列に格納
array=($str1 $str2 $str3 $str4 $str5)

③表示
$ for num in ${array[@]};do

$  echo ${num}

$ done
A
B
C
D
E

ここまでは問題ないが、、、、
もし①を下記のようにした場合
str1=A
str2=B
str3=
str4=D
str5=E

結果は以下のようになる
A
B
D
E

つまり配列は左詰めで格納されるということ。

仮にこんなロジックだと困ってしまう。
$ for num in ${array[@]};do
$ if [ "$num" = "" ];then #空白だった場合
$ echo "空白です。"
$ else
$ echo "値が入ってます。"
$ fi
$ done
値が入ってます。
値が入ってます。
値が入ってます。
値が入ってます。
空白です。

これ、3番目が空白なのに左詰にされたことで5番目が空白のように見える。
もし空白であるなしで処理を変えるようであれば、間違った処理をしてしまう。

もし結果を
値が入ってます。
値が入ってます。
空白です。
値が入ってます。
値が入ってます。

としたい場合には、

array=("$str1" "$str2" "$str3" "$str4" "$str5")
とダブルコート(")で囲ってあげましょう。

【bash】 シェルからjavaを呼ぶ ②文字コード編

2008年10月16日 17時59分05秒 | linux bash
【bash】 シェルからjavaを呼ぶ ①実行編では、
単純にシェルからjavaを呼んで、プロンプト表示させただけなので、
文字コードについて意識することはなかったと思いますが、

以下の様に、シェルとjavaで共通したファイルを使用することにより、
文字コードの問題にぶつかります。

まずはjavaファイル。これは①実行編と一緒です。
Test.javaの中身-----------------------------------------
public class Test {

 /**
  * @param args
  */
 public static void main(String[] args) {
  System.out.println("Javaファイルを実行!");
 }

}
--------------------------------------------------------

シェルのファイル。ここでちょっと細工します。
Test.shの中身-------------------------------------------
#!/bin/sh
LOG_FILE=/test/log/test.log    ←①ログファイルの場所とファイル名を設定
echo "Test.sh開始" > $LOG_FILE  ←②シェルログをログファイルに出力
java Test >> $LOG_FILE  ←③javaを実行、出力内容をログファイルに出力
echo "Test.sh終了" >> $LOG_FILE  ←④シェルログをログファイルに出力
--------------------------------------------------------

実行するコマンドを叩く
$ sh Test.sh

出力されたログファイルを確認します。
test.logの中身------------------------------------------
Test.sh開始
Java繝輔ぃ繧、繝ォ繧貞ョ溯。鯉シ・
Test.sh終了
--------------------------------------------------------

③ではいたJavaファイルの出力の部分が文字化けしています。
これは、シェルとログファイルがShift-JIS形式で、
JavaファイルがUTF-8形式であるために起こっているのです。

シェルは、Windows上でメモ帳か何かで作成してLinuxサーバに上げて実行すると、
特に文字化けせずに動作するので、Shift-JISになっていることが多いのです。
また、Shift-JISのシェルでログファイルを作成しているので(②の所)
ログファイルもShift-JISになる。

そしてJavaファイルは、Eclipceやメモ帳などで作成しLinuxサーバに上げても、
UTF-8でないとコンパイルできないので、ファイルをUTF-8に変換するかUTF-8でコンパイルし実行する。

結果、Shift-JISのログファイルにUTF-8のjavaのログが出力されるので、
上記の様な文字化けがおこる。

解決策は簡単。
シェルをUTF-8で保存、サーバに上げること。
そうすればシェルがUTF-8になる→ログもUTF-8になる。
→javaもUTF-8→みんなUTF-8になる。

以上。


ちなみに結果は以下の通り
test.logの中身------------------------------------------
Test.sh開始
Javaファイルを実行!
Test.sh終了
--------------------------------------------------------

余談ですが、シェルをShift-JISのまま実行させたい場合には、Javaファイルの出力をShift-JISにしてあげればよい。
つまり、合わせることが重要。

Javaファイルの出力をShift-JISにするのは、FileInputStreamクラスを使用して、
出力時の文字コード指定をする。
(やり方は書きません。UTF-8に合わせればよいと思っているので。)


【bash】 シェルからjavaを呼ぶ ①実行編

2008年10月16日 16時16分18秒 | linux bash
・条件①
 事前にjavaがインストールされていること。
 javaのインストールに関しては、他エントリーでじっくり説明します。

・条件②
 javaファイルを設定してコンパイル済みであること。
 (javac Test.javaを行っていること)

Test.javaの中身-----------------------------------------
public class Test {

 /**
  * @param args
  */
 public static void main(String[] args) {
  System.out.println("Javaファイルを実行!");
 }

}
--------------------------------------------------------

Test.shの中身-------------------------------------------
#!/bin/sh
java Test
--------------------------------------------------------

実行するコマンドを叩く
$ sh Test.sh
Javaファイルを実行!

↑出力されることを確認する。


【bash】 echoとprintfの違い

2008年10月14日 14時45分06秒 | linux bash
echo "test" > work.txt
printf "test" > work.txt

上記2つは同じ動作をするので、大きく違いはないし
変数+文字列の出力をprintfで行うことが多いが、
echoでも実現可能であるから、好みで使えば良いと思う。

ただ1点、改行に関してechoは注意が必要。

例えば FreeBSD・Linux 系は改行のオプションが -n 、
Solaris など SystemV 系は \c 、
bash は -n 、
tcsh はデフォルトでは -n だがシェル変数 echo_style で変更可能。
改行について悩みたくない場合は、echo コマンドではなく printf コマンドを使うこと。

echo と異なり、改行させたい場合 \n を付ける事。

% printf "abc"; printf "def"
abcdef

文字列を表示するには %s を使う
% printf "HOME=[%s]\n" $HOME

複数のフォーマットも指定できる
% printf "HOME=[%s] USER=[%s]\n" $HOME $USER

数値は %d を使う
% printf "[%d]\n" 30
[30]

5桁で右詰め
% printf "[%5d]\n" 30
[ 30]

5桁で左詰め
% printf "[%-5d]\n" 30
[30 ]

5桁でゼロパディング
% printf "[%05d]\n" 30
[00030]