2019年9月9日月曜日

Build TensorFlow Lite on Raspberry Pi 4

TesorFlow Lite Raspberry Pi 用の libtensorflow-lite.a を作る
TensorFlowの当該のページ通りにすればよい。
他のページは見ない方が良い
About 40 minutes.

Build TensorFlow Lite for Raspberry Pi

cd ~/prj
git clone https://github.com/tensorflow/tensorflow.git
cd tensorflow
./tensorflow/lite/tools/make/download_dependencies.sh
./tensorflow/lite/tools/make/build_rpi_lib.sh
ls -al tensorflow/lite/tools/make/gen/rpi_armv7l/lib
   drwxr-xr-x 2 root root     4096 Sep  9 02:32 .
   drwxr-xr-x 5 root root     4096 Sep  9 02:32 ..
   -rw-r--r-- 1 root root 12164884 Sep  9 02:32 benchmark-lib.a
   -rw-r--r-- 1 root root  5796642 Sep  9 02:32 libtensorflow-lite.a

上記のページでは
tensorflow/lite/tools/make/gen/lib/rpi_armv7/libtensorflow-lite.a
ちょっと違う(笑)

Peace!!

Build Bazel(0.29.0) on Raspberry Pi 4

Bazel 0.26.0, 0.29.0のbuildです。

1.準備

sudo apt install openjdk-8-jdk

jdk は下記では8がサポート対象となっている
8にしないとエラーが発生する。このような対応不能なエラーが発生した。
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (g1ConcurrentMark.cpp:1666), pid=5210, tid=5234
#  fatal error: Overflow during reference processing, can not continue. Please increase MarkStackSizeMax (current value: 2097152) and restart.
#
# JRE version: OpenJDK Runtime Environment (11.0.3+7) (build 11.0.3+7-post-Raspbian-5)

https://docs.bazel.build/versions/master/install-compile-source.html

もし違う場合には、確認して変更またはインストールする
下の例は0だったので、2に変更した後に、再度確認した画面
sudo update-alternatives --config javac

There are 2 choices for the alternative javac (providing /usr/bin/javac).



  Selection    Path                                          Priority   Status
------------------------------------------------------------
  0            /usr/lib/jvm/java-11-openjdk-armhf/bin/javac   1111      auto mode
  1            /usr/lib/jvm/java-11-openjdk-armhf/bin/javac   1111      manual mode
* 2            /usr/lib/jvm/java-8-openjdk-armhf/bin/javac    1081      manual mode

Press <enter> to keep the current choice[*], or type selection number:

2. ソースのダウンロード

mkdir ~/prj/bazel;cd ~/prj/bazel
$ wget https://github.com/bazelbuild/bazel/releases/download/0.29.0/bazel-0.29.1-dist.zip
$ unzip bazel-0.29.0-dist.zip

3. build前の設定と変更

環境変数追加
$ EXTRA_BAZEL_ARGS="--host_javabase=@local_jdk//:jdk"

2つのファイルを変更
compile.sh
before
bazel_build "src:bazel_nojdk${EXE_EXT}" \
  --action_env=PATH \
  --host_platform=@bazel_tools//platforms:host_platform \
  --platforms=@bazel_tools//platforms:target_platform \
  || fail "Could not build Bazel"

after
bazel_build "src:bazel_nojdk${EXE_EXT}" \
  --host_javabase=@local_jdk//:jdk \
  --action_env=PATH \
  --host_platform=@bazel_tools//platforms:host_platform \
  --platforms=@bazel_tools//platforms:target_platform \
  || fail "Could not build Bazel"

scripts/bootstrap/compile.sh
before
  run "${JAVAC}" -classpath "${classpath}" -sourcepath "${sourcepath}" \
      -d "${output}/classes" -source "$JAVA_VERSION" -target "$JAVA_VERSION" \
      -encoding UTF-8 ${BAZEL_JAVAC_OPTS} "@${paramfile}"

after
  run "${JAVAC}" -classpath "${classpath}" -sourcepath "${sourcepath}" \
      -d "${output}/classes" -source "$JAVA_VERSION" -target "$JAVA_VERSION" \
      -encoding UTF-8 ${BAZEL_JAVAC_OPTS} "@${paramfile}" -J-Xmx1024M

で、Go!!!
time comple.sh

この文字列が出ればOK
Build successful! Binary is here: /home/pi/tmp/output/bazel

次にコピーして完了
sudo cp output/bazel /usr/local/bin

tころで、こんなエラーがでた。
これは、上記の一番目の変更をしなかったから。。。
ERROR: /tmp/bazel_SwJ5aUhR/out/external/bazel_tools/tools/jdk/BUILD:492:14: Configurable attribute "actual" doesn't match this configuration: Could not find a JDK for host execution environment, please explicitly provide one using `--host_javabase.`

Peace!!

2019年8月31日土曜日

OpenCV4 Stereo matching

Stereo matchingは古くからある重要な手法。
僕も、いろいろな場面で使っている。
OpenCV4をセットアップしたあと、cpp ディレクトリーに移動

g++  `pkg-config opencv4 --cflags --libs` stereo_match.cpp -o stereo_match -std=c++11 -latomic

stereo_match ../data/aloeL.jpg ../data/aloeR.jpg --algorithm=sgbm --blocksize=3 --max-disparity=128

こんな感じでbuild とコンパイル

で、いろいろパラメータ変えるとこんな感じ


更にフィルターをかけて、、

 pip3 install scikit-learn
 sudo apt install python3-sklearn

import numpy as np
from sklearn.preprocessing import normalize
import cv2

print('loading images...')
imgL = cv2.imread('../data/aloeLs.jpg')  # downscale images for faster processing if you like
imgR = cv2.imread('../data/aloeRs.jpg')

# SGBM Parameters -----------------
window_size = 3
left_matcher = cv2.StereoSGBM_create(
    minDisparity=0,
    numDisparities=80,
    blockSize=1,
    P1=8 * 3 * window_size ** 2,
    P2=32 * 3 * window_size ** 2,
    disp12MaxDiff=1,
    uniquenessRatio=15,
    speckleWindowSize=0,
    speckleRange=2,
    preFilterCap=63,
    mode=cv2.STEREO_SGBM_MODE_SGBM_3WAY
)
right_matcher = cv2.ximgproc.createRightMatcher(left_matcher)

# FILTER Parameters
lmbda = 80000
sigma = 1.2
visual_multiplier = 1.0
wls_filter = cv2.ximgproc.createDisparityWLSFilter(matcher_left=left_matcher)
wls_filter.setLambda(lmbda)
wls_filter.setSigmaColor(sigma)

print('computing disparity...')
displ = left_matcher.compute(imgL, imgR)  # .astype(np.float32)/16
dispr = right_matcher.compute(imgR, imgL)  # .astype(np.float32)/16
displ = np.int16(displ)
dispr = np.int16(dispr)
filteredImg = wls_filter.filter(displ, imgL, None, dispr)  # important to put "imgL" here!!!

filteredImg = cv2.normalize(src=filteredImg, dst=filteredImg, beta=0, alpha=255, norm_type=cv2.NORM_MINMAX);
filteredImg = np.uint8(filteredImg)
cv2.imshow('Disparity Map', filteredImg)
cv2.waitKey()
cv2.destroyAllWindows()

Peace!!


stm1 imgKittyl.bmp imgKitty.bmp  --algorithm=sgbm --blocksize=1 --max-disparity=64


stm1 imgKittyl.bmp imgKitty.bmp  --algorithm=sgbm --blocksize=1 --max-disparity=80

stm1 imgKittyl.bmp imgKitty.bmp  --algorithm=sgbm --blocksize=9 --max-disparity=64


2019年8月21日水曜日

Oracle SQL*Plus。MinGW32は癖がある (笑)

Oracle SQL*Plusを使うなんて20年ぶり
Windows環境で実行させて、結果をLinux環境に送り別の処理をする。

例えば、前日に新規登録されたデータだけを、翌日に抽出する場合。
Linux環境では、localtime_rで比較的簡単に日付指定の文字列を作れる。
ところが、Windows環境のMinGWは基本的にWindowsに依存しているので、
同じgccを使っても、localtime*は使用できない。
gccでも、違うんだぁ

Msys MinGWは、その環境で作った実行モジュールをWindowsのコマンドプロンプトで実行できない。
それをするなら、MinGWだけをインストールする必要がある。
MinGW | Minimalist GNU for Windows

でも、MinGWはWindowsに依存しているのでLinuxとの違いが発生する。
多分、今回のlocaltime*だけだと思うけど、、、

まぁ、やるといろいろ起こります。勉強勉強

で、今回のソースをドーンと

Peace!!


SQL*Plusを起動するバッチ

@ECHO OFF
:START
ECHO ---------------------------------------------------
ECHO 前日新規に登録された品目情報を出力します。
ECHO ---------------------------------------------------
CD %~dp0
DEL hinsabun.csv
hinsabun.exe > hinsabun.sql
@ECHO SQLを実行中です。しばらくお待ち下さい..
@ECHO -------------------------------
sqlplus /nolog @"hinsabun.sql" USER PASSWORD 192.168.XXX.XXX/ORCL
@ECHO -------------------------------
@ECHO 完了しました。
EXIT

localtime_r を使わない処理

#include <stdio.h>
#include <string.h>
#include <time.h>

#define PRS(A)  printf("%s\n", A)
char    *mn[]= {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

int main(int argc, char* argv[]){
    char    szTime[15];
    char    szBuf[256], szBuf1[64];
    char    szMn[4], szDmy[10];
    int     n = 1, iDay, i, iMn, iYr;
    struct tm tm;
    time_t t;
    
    time(&t);
    t -= (86400 * n);
    strcpy(szBuf1, ctime(&t));
    strcpy(szDmy, strtok(szBuf1, " "));
    strcpy(szMn, strtok(NULL, " "));
    iDay = atoi(strtok(NULL, " "));
    strcpy(szDmy, strtok(NULL, " "));
    iYr = atoi(strtok(NULL, " "));
    for (i = 0; i < 12; i++) {
        if (strcmp(szMn, mn[i]) == 0){
            iMn = i + 1;
            break;
        }
    }
    sprintf(szTime, "%04d%02d%02d", iYr, iMn, iDay);

    //localtime_r(&t, &tm);
    //sprintf(szTime, "%04d%02d%02d%02d%02d%02d",
    //        tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
    //        tm.tm_hour, tm.tm_min, tm.tm_sec);
    //sprintf(szTime, "%04d%02d%02d",
    //          tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
    
    PRS("connect &&1/&&2@&&3");
    PRS("spool off");
    PRS("set echo off");
    PRS("set heading off");
    PRS("set termout off");
    PRS("set pause off");
    PRS("set pagesize 0");
    PRS("set linesize 10000");
    PRS("--set trimout on");
    PRS("set trimspool on");
    PRS("set feedback off");
    PRS("set verify off");
    PRS("set colsep '|'");
    PRS("spool hinsabun.csv");
    sprintf(szBuf, "SELECT ITEM_CD, ITEM_DIV, ITEM_NAME1, ITEM_NAME2, STD_UNIT, STD_UNITPRICE, UNIT2, UNIT_CONV_RATE,ITEM_NAME4,REGIST_DATE, UPDATE_DATE from DFW_M040M where REGIST_DATE >= to_date('%s', 'yyyymmdd');", szTime);
    PRS(szBuf);
    PRS("spool off");
    PRS("exit");
    
    return 0;
}

Peace!!

2019年8月11日日曜日

AsyncTaskによるDB非同期処理をListenerを使ってクラス化

Android ActivityでDBを頻繁に使うプログラムを開発する場合に、
前項のようなコードをActivity内に組込むのはやめたい。
クラス化にあたっての課題は、処理の結果を呼び出したクラスに渡すか?
非同期処理処理を踏まえてどうするか。。。
で、先人の知恵を借りてListenerを使って呼び出し側で非同期処理の終了を
解るようにして、一件落着
ますます、便利になった。
Peace!!

ソースの先頭には、使い方を書いた。
サーバーサイドのDBプログラムは別途必要です。
ソースコード、どーんと(笑)

/***********************************************************
 * AsyncTask<型1, 型2,型3>
 *   型1 … Activityからスレッド処理へ渡したい変数の型
 *          ※ Activityから呼び出すexecute()の引数の型
 *          ※ doInBackground()の引数の型
 *   型2 … 進捗度合を表示する時に利用したい型
 *          ※ onProgressUpdate()の引数の型
 *   型3 … バックグラウンド処理完了時に受け取る型
 *          ※ doInBackground()の戻り値の型
 *          ※ onPostExecute()の引数の型
 *   ※ それぞれ不要な場合は、Voidを設定すれば良い
 * --------------------------------------------------------------
 * 呼び出す側に以下を追加する
 ********************************************************************************
 * 汎用DBアクセスクラス SqlOpeAsyncTask を使う場合のListener設定
 * クラスを使う側で設定する。
 * onDestroyは、使うクラス側で重ならなければ使えるかも。未確認
 * @return
 * /
    private SqlOpeAsyncTask.Listener createListener(){
        return new SqlOpeAsyncTask.Listener(){
            @Override
            public void onSuccess(String ret){
                // 以下は個々のプログラム毎に記述
                etKata.setText(ret);
            }
        };
    }
    @Override
    protected void onDestroy() {
        SqlOpeAsyncTask.setListener(null);
        super.onDestroy();
    }

    // 呼び出し例
        String in1 =  getResources().getString(R.string.url_srv_gets1);
        String in2 =  "?100:select kata,tana,hinc,kazu from zaiko where hinc = '15916-1' and tana <> 'REFER' order by tana DESC; ";
        SqlOpeAsyncTask retAsyn = new SqlOpeAsyncTask();
        retAsyn.setListener(createListener());
        String inStr = in1 + in2;
        Log.d(TAG, "before Async execute");
        retAsyn.execute(inStr);
 ***********************************************************************/

package com.futureagri.app.thn.hd.java;

import android.nfc.Tag;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/******************************************************************
 * 非同期でデータベース処理をするクラス。
 ******************************************************************/
public  class SqlOpeAsyncTask  extends AsyncTask<String, Void, String> {
    private Listener listener;

    private static final String TAG = "SqlOpeAsyncTask";
    private String retString = "";
    private TextView textView;

    /********************************************************************
     * メインスレッドとは別のスレッドで実行されます。
     * 非同期で処理したい内容を記述します。
     * このメソッドだけは必ず実装する必要があります
     * @param data
     * @return
     */
    @Override
    //protected String doInBackground(Object[] data) {
    public String doInBackground(String... data) {
        // target URL
        String urlStr = (String)data[0];
        Log.d(TAG, "doInBackground: " + "input sql=" + urlStr);
        // Variable of set result texts
        //StringBuilder result = new StringBuilder();
        String result = "";
        //http接続を行うHttpURLConnectionオブジェクトを宣言。finallyで確実に解放するためにtry外で宣言。
        HttpURLConnection con = null;
        //http接続のレスポンスデータとして取得するInputStreamオブジェクトを宣言。同じくtry外で宣言。
        InputStream is = null;
        int i = 10;
        try {
            //URLオブジェクトを生成。
            URL url = new URL(urlStr);
            //URLオブジェクトからHttpURLConnectionオブジェクトを取得。
            con = (HttpURLConnection) url.openConnection();
            //http接続メソッドを設定。
            con.setRequestMethod("GET");
            //接続。
            con.connect();
            final int   status = con.getResponseCode();
            if (status == HttpURLConnection.HTTP_OK) {
                // Success HTTP GET method
                is = con.getInputStream();
                result = is2String(is);
                is.close();
            }else {
                Log.d(TAG, "doInBackground: HTTP response error");
            }
        } catch (MalformedURLException ex) {
            ex.printStackTrace();
            //} catch (ProtocolException ex) {
            //ex.printStackTrace();
            Log.d(TAG, "doInBackground: HTTP MalformedURLException");
        } catch (IOException ex) {
            ex.printStackTrace();
            Log.d(TAG, "doInBackground: HTTP IOException");
        } finally {
            // HttpURLConnectionオブジェクトがnullでないなら解放。
            if (con != null) {
                con.disconnect();
            }
            // InputStreamオブジェクトがnullでないなら解放。
            if (is != null) {
                try {
                    is.close();
                } catch (IOException ex) {
                    Log.d(TAG,"doInBackground: HTTP close is IOException");
                }
            }
        }
        // 非同期で取得したデータをセットする
        if ( i == 0) {
            Log.d(TAG, "doInBackground: HTTP return : error end");
            return "-99999";
        }else {
            //return result.toString();
            retString = result;
            return result;
        }
    }
    /*****************************************************************************
     * doInBackgroundメソッドの実行後にメインスレッドで実行されます。
     * doInBackgroundメソッドの戻り値をこのメソッドの引数として受け取り、
     * その結果を画面に反映させることができます
     * @param result
     */
    @Override
    public void onPostExecute(String result) {
        //toastMake(result, 0, -200);
        Log.d(TAG, "onPostExecute: result :" + result);
        String[] ret = result.split("\\|");  // Mac \ -> (option + ¥)
        int iMode = Integer.parseInt(ret[0]);   // 呼び出した処理番号
        int cnt  = Integer.parseInt(ret[1]);    // 検索数
        int retu = Integer.parseInt(ret[2]);    // 列数
        Log.d(TAG, "onPostExecute: mode:cnt:retu=" + iMode + ":" + cnt + ":" + retu);
        //-------------------------------------------------------------
        //  mode=100 kata,tana,hinc,kazu
        //-------------------------------------------------------------
        if (iMode == 100) {
            retString = iMode + "|" + cnt + "|" + retu + "|";
            for (int i = 0; i < cnt * retu; i++) {
                retString = retString + ret[3 + i] + "|";
            }
        }
        if (listener != null) {
            listener.onSuccess(retString);
        }
    }
    /*****************************************************************************
     * InputStreamオブジェクトを文字列に変換するメソッド。変換文字コードはUTF-8。
     *
     * @param is 変換対象のInputStreamオブジェクト。
     * @return 変換された文字列。
     * @throws IOException 変換に失敗した時に発生。
     */
    private String is2String(InputStream is) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
        StringBuffer sb = new StringBuffer();
        char[] b = new char[2048];
        int line;
        while(0 <= (line = reader.read(b))) {
            sb.append(b, 0, line);
        }
        return sb.toString();
    }
    /************************************************************
     * Listener 処理を定義する
     * 
     * @param listener
     */
    void setListener(Listener listener) {
        this.listener = listener;
    }
    interface Listener {
        void onSuccess(String  count);
    }
}

2019年8月2日金曜日

Android 非同期処理でサーバサービスを利用する

スマフォからデータベース処理する方法のメモ
至る所に掲載されているので、あくまでも自分のメモ

基本的にデータ量が少ないのでGETメソッドで説明
ちなみに、com.squareup.okhttp3:okhttp:3.12.1 を使っています。

1.基本的な流れ

・スマフォ側で、起動するサーバサイドのサービスの定義と渡す情報の設定
・非同期処理部分(AsyncTask)の記述。
   基本部分は一度書けば使いまわし。
   大事なのは、onPostExecuteの部分。
   この部分にサーバから戻ってきたデータに対する処理を記述する。
   この投稿では、データをチェックしたあと、Intentで別のActivity起動している

2. スマフォ側でサーバプログラム起動の準備

オブジェクト作成と、起動サービス、引数の設定
非同期処理のHTTPサービスのオブジェクトを作成して実行

Object[] data = new Object[3];
data[0] = getResources().getString(R.string.url_srv_reg_payout);
// 引数を設定する
data[1] =

hdPartsActivity.SqlSelectReciever receiver =
               new hdPartsActivity.SqlSelectReciever();
receiver.execute(qq);

3.非同期処理(AsyncTask)を担当する本体部分

   private class SqlSelectReciever extends AsyncTask<String, String, String> {
        public SqlSelectReciever() {
        }
        @Override
        public String doInBackground(String... params) {
            // target URL
            String urlStr = (String)params[0];
            Log.d(TAG, " SqlSelectReciever: " + "sql=" + urlStr);
            // Variable of set result texts
            //StringBuilder result = new StringBuilder();
            String result = "";
            //http接続を行うHttpURLConnectionオブジェクトを宣言。finallyで確実に解放するためにtry外で宣言。
            HttpURLConnection con = null;
            //http接続のレスポンスデータとして取得するInputStreamオブジェクトを宣言。同じくtry外で宣言。
            InputStream is = null;
            int i = 10;
            try {
                //URLオブジェクトを生成。
                URL url = new URL(urlStr);
                //URLオブジェクトからHttpURLConnectionオブジェクトを取得。
                con = (HttpURLConnection) url.openConnection();

                //http接続メソッドを設定。
                con.setRequestMethod("GET");
                //接続。
                con.connect();
                final int   status = con.getResponseCode();
                if (status == HttpURLConnection.HTTP_OK) {
                    // Success HTTP GET method
                    is = con.getInputStream();
                    result = is2String(is);
                    Log.d(TAG, " HTTP connect result=" + result);
                    is.close();
                }else {
                    Log.d(TAG, "HTTP response error");
                }
            } catch (MalformedURLException ex) {
                ex.printStackTrace();
                //} catch (ProtocolException ex) {
                //ex.printStackTrace();
                Log.d(TAG, "HTTP MalformedURLException");
            } catch (IOException ex) {
                ex.printStackTrace();
                Log.d(TAG, "HTTP IOException");
            } finally {
                // HttpURLConnectionオブジェクトがnullでないなら解放。
                if (con != null) {
                    Log.d(TAG, "HTTP not null");
                    con.disconnect();
                }
                // InputStreamオブジェクトがnullでないなら解放。
                if (is != null) {
                    Log.d(TAG,"HTTP close InputStream");
                    try {
                        is.close();
                    } catch (IOException ex) {
                        Log.d(TAG,"HTTP close is IOException");
                    }
                }
            }
            //JSON文字列を返す。
            if ( i == 0) {
                Log.d(TAG, "HTTP return : error");
                return "error";
            }else {
                //Log.d("doInBackground:return:", result.toString());
                //return result.toString();
                //Log.d(TAG, "HTTP return : normal");
                return result;
            }
        }
        //=================================================
// サーバから戻ってきた戻り値に対する処理
// ここの部分が大事。
// Activityの中で複数の非同期処理をする時もここにを書く。
// 因みに僕は戻り値の最初の情報cntとretuを使って複数対応している。
//=================================================
        @Override
        public void onPostExecute(String result) {
            String[] ret = result.split("\\|");  // Mac \ -> (option + ¥)
            int cnt  = Integer.parseInt(ret[0]);  // 1行目:検索数
            int retu = Integer.parseInt(ret[1]);  // 1行目:列数
            Log.d(TAG, "cnt:retu=" + cnt + ":" + retu);
                 ・
                 ・ ここにいろいろ処理を書く、
                 ・
            Intent intent = new Intent(hdPartsActivity.this, SqlGetList2.class);
            // intentへ添え字付で値を保持させる
            intent.putExtra( "hdkey", hks);
            // 返却したい結果ステータスをセットする
            setResult( SqlGetList2.RESULT_OK, intent );
            //startActivity(new Intent(hdSeibanListActivity.this, SqlGetList2.class));
            startActivity(intent);
            //Log.d(TAG, " Intent after : startActivity(intent)");
            return;
        }
        /**
         * InputStream objectを文字列に変換するmethod。変換文字codeはUTF-8。
         *
         * @param is 変換対象のInputStreamオブジェクト。
         * @return 変換された文字列。
         * @throws IOException 変換に失敗した時に発生。
         */
        private String is2String(InputStream is) throws IOException {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            StringBuffer sb = new StringBuffer();
            char[] b = new char[1024];
            int line;
            while(0 <= (line = reader.read(b))) {
                sb.append(b, 0, line);
            }
            return sb.toString();
        }
    }

Peace!!

2019年7月22日月曜日

MySQL 自動バックアップ

MySQLバックアップの忘備録

1.バックアップ用シェル

#!/bin/sh

# Set mask for other user cann't read
#umask 077

# backup file
# Retention period
period=31

# directory for backup files
dirpath='/home/pi/backup/mysql'

# backup file naming
filename=`/bin/date +%y%m%d%H`

# excute
/usr/bin/mysqldump --opt --all-databases --events --default-character-set=binary -u root --password=xxxxx| /bin/gzip > $dirpath/$filename.sql.gz
#/usr/bin/mysqldump --opt --all-databases --events --default-character-set=binary -u root --password=xxxxx > /tmp/filename.sql

/bin/cp $dirpath/$filename.sql.gz $dirpath/today

# delete old backup files
oldfile=`/bin/date --date "$period days ago" +%y%m%d%H`
/bin/rm -f $dirpath/$oldfile.sql.gz

2.crontabの設定

0 2 * * *  /home/pi/prj/sql/mysql_backup.sh > /tmp/cron-bk.stdout 2 > /tmp/cron-bk.stderr || [ $? -eq 1 ]
15 12 * * *  /home/pi/prj/sql/mysql_backup.sh > /tmp/cron-bk.stdout 2 > /tmp/cron-bk.stderr || [ $? -eq 1 ]

Peace!!