基本的な確認コマンドその1

  • OSのバージョン確認

    cat /etc/issue
    CentOS release 6.6 (Final)
    Kernel \r on an \m
    
  • OSのbit数確認

    uname -a
    Linux z-area.net 2.6.32-504.23.4.el6.x86_64 #1 SMP Tue Jun 9 20:57:37 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
    

【Java】jarファイル付のJavaコンパイル

基本的なことをメモ。

  • 前提条件
    /home/testにjarファイル、Javaファイルがある。
    Javaファイルは処理内でjarファイル内のメソッドを利用する。
  • コンパイルと実行

    cd /home/test
    javac -cp .:./jarファイル javaファイル
    java -cp .:./jarファイル クラス名
    
  • クラスパスの区切り文字
    Linuxはコロンになる。
    Windowsはセミコロンになる。
  • 実行時のルートパス
    実行時に-cp指定がないとJAVA_HOMEがルートになる。
    .を指定することで現在いるディレクトリがルートになる。

【jQuery】動的追加したオブジェクトにイベントを設定

jQueryでオブジェクト(ボタンやリンク)にイベントを設定した場合、
画面表示時点で存在しているオブジェクトを押下すると
設定したイベントがもちろん実行されますが、
動的追加したオブジェクトでは押下しても設定したイベントが
実行されない事象があったので、解決策をメモしておきます。


  • 下記のようなHTML(Thymeleaf)があると仮定し、
    追加ボタンを押下すると行(<tr>~</tr>)が追加されるとする。

    <table class="table">
      <thead>
        <tr>
          <th><span th:text="${no}"></span></th>
          <th><span th:text="${gaiyou}"></span></th>
          <th><span th:text="${naiyou}"></span></th>
          <th><span th:text="${link}"></span></th>
          <th><span th:text="${aruaru}"></span></th>
        </tr>
      </thead>
      <tbody id="van-tbody">
        <tr th:each="van : ${vanAll}" >
          <td><span th:text="${van.no}"></span></td>
          <td><span th:text="${van.gaiyou}"></span></td>
          <td><span th:text="${van.naiyou}"></span></td>
          <td><span th:text="${link}"></span></td>
          <td>
            <span th:text="${van.aruaru}"></span><button id="button-plus + '${van.no}'" type="button" class="btn btn-plus"><span class="glyphicon glyphicon-plus-sign"></span></button>
          </td>
        </tr>
      </tbody>
    </table>
    
  • オブジェクトのイベント設定(静的)
    上記HTMLにおいて初期状態で2行分があるとし、
    その2行分のみにイベントを設定する場合、下記のようなイベント設定で問題なし。

    • clickメソッド
      古いタイプのイベント設定方法。
      「button」に設定してしまうとテーブル外のボタンにもイベントが設定されてしまうので、
      テーブル内のボタンだけが利用しているスタイルシート「btn-plus」にイベントを設定している。

      <script type="text/javascript">
      <!--
      $(document).ready(function() {
        $('.bth-plus').click(function() {
          alert('クリックしました');
        });
      });
      -->
      </script>
      
    • onメソッド
      新しいタイプのイベント設定方法。
      こちらの設定方法が推奨されており、「バインド」と呼ばれる。
      onメソッドの第1引数はスペースで区切れば複数のイベントも設定可能。
      例:’click keyup’

      <script type="text/javascript">
      <!--
      $(document).ready(function() {
        $('.bth-plus').on('click', function(){
          alert('クリックしました');
        });
      });
      -->
      </script>
      
  • オブジェクトのイベント設定(動的)
    上記HTMLにおいて初期状態で2行分があるとし、
    3行目、4行目と増えてもイベントを動作させたい場合、
    下記のようにイベント自体は親に設定しておいて、
    onメソッドの第2引数に本来イベントを設定したいオブジェクトを指定します。

    • onメソッド(第2引数追加版)
      このような設定方法を「デリゲート」という。

      <script type="text/javascript">
      <!--
      $(document).ready(function() {
        $('table').on('click', '.btn-plus', function(){
          alert('クリックしました');
        });
      });
      -->
      </script>
      

【SpringMVC】GoogleChartsの利用

画面でボタン押下時にモーダルダイアログを表示し、
GoogleChartsを利用し、グラフを表示します。

  • 画面の処理
    ボタンにIDを追加する。

    <button id="bsButton" type="button" class="btn btn-danger">グラフ表示</button>
    

    モーダルダイアログの表示領域を設定する。

    <!-- Chart Create Modal -->
    <div th:fragment="chart-create-modal">
      <div class="modal fade bs-example-modal-lg" id="myModal" tabindex="-1">
        <div class="modal-dialog modal-lg">
          <div class="modal-content">
            <div class="modal-header">
              <button type="button" class="close" data-dismiss="modal">&times;</button>
              <h3 class="modal-title" id="myModalLabel">タイトル</h3>
            </div>
            <div class="modal-body">
              <div id="chart_div" style="width: 400px; height: 400px;"></div>
            </div>
          </div>
        </div>
      </div>
    </div>
    

    JavaScriptでサーバー側からデータ取得処理を呼び出し
    GoogleのAPIにデータを渡します。

    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <script type="text/javascript">
    google.load("visualization", "1", {
      packages : [ "corechart" ]
    });
    <!--
    $(document).ready(function() {
      $("#bsButton").click(showChart);
    });
    
    function showChart() {
      $.post(
        '/sample/showChart', // URL
        {},                  // Userデータ
        function(result) {
          $("#myModalLabel").html("テストグラフ");
          $('#myModal').modal('show');
          var data = google.visualization.arrayToDataTable(result);
          var options = {
            title : 'テストグラフタイトル',
            vAxis : {title : "縦座標"},
            hAxis : {title : "横座標"},
            seriesType : "bars",
            series : {5 : {type : "line"}}
          };
          var chart = new google.visualization.ComboChart(document.getElementById('chart_div'));
          chart.draw(data, options);
        },                   // 成功時のコールバック
        "json"               // JSON形式
      );
    }
    
  • サーバの処理
    サーバー側からデータを取得しJSON形式で返します。

    @RequestMapping(value = "/showChart", method = RequestMethod.POST)
    @ResponseBody
    public Object[][] showChart(WebRequest request) {
        int rows = 3;
        int cols = 6;
        Object[][] result = new Object[rows][cols];
        int row=0, col=0;
        // result配列にヘッダとデータを設定
        return result;
    }
    

【SpringMVC】バリデーションチェック

SpringMVCでバリデーションチェックを実施します。
例として、作業時間入力用のクラスがあるとして、それを複数所持するListがあるとし、
JSPでそのListをループし、作業時間入力レコードを複数表示およびチェックします。

  • バリデーションチェックのjarファイル追加
    「【SpringMVC設定】ファイルその4」を参考にpom.xmlにjarファイルを追加する。
  • アノテーション追加
    作業時間入力用のクラスは全て必須項目とするため、「@NotNull」を追加する。

    public class DayTimeWork implements Serializable {
        private static final long serialVersionUID = 1L;
    
        @NotNull
        private String ankenNo;
        @NotNull
        private String startTime;
        @NotNull
        private String endTime;
    
        アクセサメソッドは省略。
    }
    

    作業時間入力用のクラスを保持するListには「@Valid」を追加する。
    「@Valid」はネストしたクラスも検証対象とする場合、追加します。

    public class DayTime implements Serializable {
        @Valid
        private List<DayTimeWork> dayTimeWork;
    
        アクセサメソッドは省略。
    }
    
  • コントローラーへの設定追加
    Javaコントローラーにバリデーションチェックを実施するための設定を追加する。
    「@Validated」の次の項目にBindingResultを記載しないと
    実行時にValidationExceptionが発生する。

    
    @Controller
    public class InputController {
    
        @InitBinder
        public void initBinder(WebDataBinder binder) {
            // bind empty strings as null
            binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
        }
    
        @RequestMapping(value = "/updateDayTime", method = RequestMethod.POST)
        public String updateDayTime(
                @ModelAttribute(value = "dayTime") DayTime dayTime, 
                final @Validated DayTime inputDayTime, 
                BindingResult result, 
                Model model) {
            // 処理省略
        }
    }
    
  • JSPへの設定追加
    JSPでバリデーションチェック結果を取得する。
    Thymeleafのタグを利用し、全項目内でエラーが1つでもあれば、
    変数errとしてエラーを取得し、表示しています。

    <form class="form-horizontal" action="#" th:action="@{/updateDayTime}" th:object="${dayTime}" method="post">
    <fieldset>
      <ul th:if="${#fields.hasErrors('*')}">
        <li th:each="err : ${#fields.errors('*')}" th:text="${err}">Input is incorrect</li>
      </ul>
    </fieldset>
    </form>
    

    Thymeleafのタグを利用し、エラー項目のテキストボックスの枠を赤くしたり、
    入力がない場合、placeholderで「案件番号」という文字を初期表示することも可能。

    <form class="form-horizontal" action="#" th:action="@{/updateDayTime}" th:object="${dayTime}" method="post">
      <table class="table">
        <!-- 処理省略 -->
        <tr th:each="vc, row : *{dayTimeWork}" >
          <td th:class="${#fields.hasErrors('dayTimeWork[__${row.index}__].ankenNo')}? has-error"  align="center">
          <input type="text" th:field="*{dayTimeWork[__${row.index}__].ankenNo}" placeholder="案件番号" class="form-control" />
          </td>
        </tr>
      </table>
    </form>
    

LFTPコマンドの外だし

シェルでLFTPでファイルを取得する必要があったので。

#!/bin/sh
echo "処理開始" >> result.log

# LFTP接続
lftp -f command.txt >> ftp.log

# ftp.logに先頭から始まる「abc*」がない場合
if ! grep "^abc*" ftp.log > /dev/null 2>&1; then

    # ftp.logの内容をresult.logに移し、ftp.logを初期化し、処理正常
    cat ftp.log >> result.log
    echo "処理終了(ファイルなし)" >> result.log
    cp /dev/null ftp.log
    exit 0

# ftp.logに先頭から始まる「abc*」がある場合
else

    # ftp.logの内の先頭から始まる「abc*」をgrepする
    for X in `grep "^abc*" ftp.log`
    do
        # ファイル名(grep結果)が取得できている場合(-eが存在確認)
        if [ ! -e $X ]; then

            # ftp.logの内容をresult.logに移し、ftp.logを初期化し、処理異常
            cat ftp.log >> result.log
            echo "ファイル転送エラー" >> result.log
            cp /dev/null ftp.log
            exit 1
        fi
    done
fi

# ftp.logの内容を初期化し、処理正常
echo "処理終了" >> result.log
cp /dev/null ftp.log
exit 0;
command.txtの内容
open IP
user ユーザ名 パスワード
cd /test
cls abc*.txt
mget abc*.txt

ftp.logは処理が終了すると0バイトに初期化するが、
処理中は下記状態となる。

【正常の場合(取得ファイルあり)】
abc1.txt
abc2.txt

【正常の場合(取得ファイルなし)】
ファイル取得エラー

【異常の場合】
abc1.txt
abc2.tx
ファイル転送エラー

【CentOS】cronの自動実行

cronは決められた時刻にコマンドを定期的に実行させるためのデーモンプロセスです。

  • cronの起動確認

    /etc/rc.d/init.d/crond status
    crond (pid  xxxx) を実行中...
    
  • cronの起動

    /etc/rc.d/init.d/crond start
    
  • cronの設定ファイル(設定変更非推奨)

    cat /etc/crontab 
    
    # 「/etc/password」の記述に関係なく、強制的にここで定義されたシェルを利用
    SHELL=/bin/bash
    # パスの設定
    PATH=/sbin:/bin:/usr/sbin:/usr/bin
    # cronの実行結果をここで指定されたユーザー宛にメール
    MAILTO=root
    # cronによりプログラム実行されるときのカレントディレクトリ
    HOME=/
    
  • cronへの登録(手動)

    crontab -e
    
    * * * * * プログラム名
    1番目:分(0 - 59)
    2番目:時(0 - 23)
    3番目:日(1 - 31)
    4番目:月(1 - 12)
    5番目:曜日(0 - 6)(日曜日が0) or (sun,mon,tue,wed,thu,fri,sat)
    

    編集が完了すると下記パスにユーザ名のファイルに保存される。

    /var/spool/cron/ユーザ名
    
  • cronへの登録(自動)
    対象ディレクトリに配置するだけで自動実行される。

    /etc/cron.hourly:1時間に1回実行
    /etc/cron.daily:1日に1回実行
    /etc/cron.weekly:1週間に1回実行
    /etc/cron.monthly:1ヶ月に1回実行
    

【CentOS】myDNSへのグローバルIP自動通知

myDNSへのグローバルIPの通知はDiCEで実施していたのですが、
最近はWindowsを立ち上げることが減ってきたので、
CentOS側にシェルを作成して自動通知することに。

【起動条件】
1日1回起動

【通知条件】
(A) 前回通知したグローバルIPと起動時のグローバルIPが異なる場合
または
(B) 前回実行が「ERROR」の場合
または
(C) 前回実行から5日経過している場合

通知条件(A)は「/etc/cron.daily」にシェルを配置することで
システムで自動的に1日1回起動するようにします。
通知条件(B)と(C)はシェルで実装します。

  • シェル作成

    vi /etc/cron.daily/mydns.sh
    
  • シェル内容

    #!/bin/bash
    
    # 更新時の日付・時刻、IPアドレス、更新結果ログファイル
    CURRENT_IP_FILE='/var/tmp/current_ip.log'
    # 更新時にMyDNS.jpから返されるHTMLファイル
    LOG_FILE='/var/tmp/ip_update.html'
    
    # ieserver.netのグローバルIP確認でグローバルIPを取得
    IP_ADDR_CHK='http://ieserver.net/ipcheck.shtml'
    # myDnsのログインページ
    DDNS_UPDATE="http://www.mydns.jp/login.html"
    USR='myDNSのユーザ名'
    PSW='myDNSのパスワード'
    STATUS='login_status = 1\.'
    
    if [ -f ${CURRENT_IP_FILE} ]; then
        CURRENT=`cat ${CURRENT_IP_FILE}`
        CURRENT_IP=`echo ${CURRENT} | cut -d " " -f 3`
        CURRENT_DT=`echo ${CURRENT} | cut -d " " -f 1-2`
        CURRENT_RTN=`echo ${CURRENT} | cut -d " " -f 4`
    else
        CURRENT_IP='0.0.0.0'
        CURRENT_DT='2000/01/01 00:00:00'
        CURRENT_RTN='ERROR'
    fi
    
    NEW_IP=`wget -q -O - ${IP_ADDR_CHK}`
    NEW_DT=`date +"%Y/%m/%d %H:%M:%S"`
    
    DIFF_DAY=`expr \( \`date -d"${NEW_DT}" +%s\` - \`date -d"${CURRENT_DT}" +%s\` \) / 86400`
    
    if ( [ ${NEW_IP} != "0.0.0.0" ] && [ ${NEW_IP} != ${CURRENT_IP} ] ) \
    || [ ${CURRENT_RTN} = "ERROR" ] \
    || [ ${DIFF_DAY} -gt 5 ]; then
        wget -q --user=${USR} --password=${PSW} -O ${LOG_FILE} ${DDNS_UPDATE}
        if [ $? -eq 0 ] && grep -q "${STATUS}" ${LOG_FILE}; then
            echo "${NEW_DT} ${NEW_IP} OK" > ${CURRENT_IP_FILE}
            MSG="OK"
        else
            echo "${NEW_DT} ${CURRENT_IP} ERROR" > ${CURRENT_IP_FILE}
            MSG="ERROR"
        fi
    fi
    
  • シェル実行権限付与

    chmod 755 /etc/cron.daily/mydns.sh
    

【SpringMVC】でThymeleafを利用

JSPではサーブレット側の処理を記載していないと
値が渡せないので、画面側のデザインが値ありで確認しにくかったりしていましたが、
Thymeleafでは値がある場合、ない場合の動作を切り分けられる点、
また便利なタグが多い点から利用してみます。

  • src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml

    • コントローラーの処理終了後に呼び出される画面用ファイルの指定
      この部分を変更します。

      【変更前】

      <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
      </beans:bean>
      

      【変更後】

      <beans:bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
        <beans:property name="prefix" value="/WEB-INF/templates/" />
        <beans:property name="suffix" value=".html" />
        <beans:property name="templateMode" value="HTML5" />
      </beans:bean>
      
      <beans:bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
        <beans:property name="templateResolver" ref="templateResolver" />
      </beans:bean>
      
      <beans:bean class="org.thymeleaf.spring3.view.ThymeleafViewResolver">
        <beans:property name="characterEncoding" value="UTF-8" />
        <beans:property name="templateEngine" ref="templateEngine" />
      </beans:bean>
      
  • pom.xml
    「dependencies」タグの中に下記内容を追加します。

    • Thymeleafライブラリー

      <!-- Thymeleaf -->
      <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf-spring3</artifactId>
        <version>2.1.2.RELEASE</version>
      </dependency>
      

【SpringMVC】設定ファイルその4

  • pom.xml
    拡張設定の内容を記載します。
    前回の設定と同様に「dependencies」タグの中に下記内容を記載していきます。

    • バリデーションチェックライブラリー

      <!-- Validator -->
      <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>1.0.0.GA</version>
      </dependency>
      <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>4.3.1.Final</version>
      </dependency>
      
    • JavaオブジェクトをJSON形式に変換しGoogleAPIに渡すライブラリー

      <!-- Jacson -->
      <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-core-asl</artifactId>
        <version>1.6.4</version>
      </dependency>
      <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>1.6.4</version>
      </dependency>
      <!-- GoogleAPI -->
      <dependency>
        <groupId>com.googlecode.json-simple</groupId>
        <artifactId>json-simple</artifactId>
        <version>1.1</version>
      </dependency>
      
    • JUnitライブラリー

      <!-- JUnit -->
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.7</version>
        <scope>test</scope>
      </dependency>