phpMyAdmin 経由で、コマンドラインから DB のデータをエクスポートしてみる

# ０．はじめに

共用サーバなど、
外部から phpMyAdmin 経由でしか DB へアクセスできない場合でも、
コマンドラインから自動で DB をエクスポートしたいな、
と思い、やってみました。

# １．プログラム
1. はい。
　
    という事で、
    以下のシェルスクリプトを実行すればできると思います。

    で、解説をちょっと後述しときます。

    あと、phpMyAdmin のバージョンは 4.0.10.17 でしか確認していないので、
    うまくいかない場合は、バージョンに合わせて修正して下さい。

    ```bash:phpMyAdmin_Export.bash
    #!/bin/bash
    
    # ---1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----
    
    # ==============================================================================
    #
    # phpMyAdmin_Export.bash
    #
    #   * phpMyAdmin : 4.0.10.17
    #
    # ==============================================================================
    
    mypath=${0%/*}
    myname=${0##*/}
    mybase=${myname%.*}
    mydate=`date +'%Y-%m-%d'`
    
    LOG()
    {
        printf "[%-10s %-8s] (%06d) %-50s\n" \
        `date '+%Y-%m-%d %H:%M:%S'` "${1}" "${2}"
        printf "[%-10s %-8s] (%06d) %-50s\n" \
        `date '+%Y-%m-%d %H:%M:%S'` "${1}" "${2}">>"${mypath}/${myname}.log"
    }
    
    # ------------------------------------------------------------------------------
    # Set
    # ------------------------------------------------------------------------------
    
    LOG ${LINENO} "<<<<<<<< Set >>>>>>>>"
    
    USERNAME="[phpMyAdmin へのログインユーザー]"
    PASSWORD="[phpMyAdmin へのログインパスワード]"
    COOKIES_FILE="${mypath}/${myname}.tmp"
    BASE_URL="[phpMyAdmin の URL]"
    EXPORT_URL="${BASE_URL}export.php"
    
    OUTFOLDERPATH="[出力先フォルダ]"
    
    DBLIST="
    [出力する DB のリスト (※一行ずつ)]
    "
    
    LOG ${LINENO} "USERNAME:[${USERNAME}]"
    LOG ${LINENO} "PASSWORD:[****]"
    LOG ${LINENO} "COOKIES_FILE:[${COOKIES_FILE}]"
    LOG ${LINENO} "SERVER_NUM:[${SERVER_NUM}]"
    LOG ${LINENO} "BASE_URL:[${BASE_URL}]"
    LOG ${LINENO} "EXPORT_URL:[${EXPORT_URL}]"
    LOG ${LINENO} "OUTFOLDERPATH:[${OUTFOLDERPATH}]"
    
    # ------------------------------------------------------------------------------
    # Program Start
    # ------------------------------------------------------------------------------
    
    LOG ${LINENO} "<<<<<<<< Program Start >>>>>>>>"
    date_s=`date +'%Y/%m/%d %H:%M:%S'`
    
    function cleanup {
    [ -e ${COOKIES_FILE} ] && rm -f ${COOKIES_FILE}
    }
    
    trap 'cleanup' 0 1 2 3 15
    
    TOKEN=$(wget \
    ${BASE_URL} \
    --quiet \
    --no-check-certificate \
    --auth-no-challenge \
    --http-user=${USERNAME} --http-passwd=${PASSWORD} \
    --keep-session-cookies \
    --save-cookies=${COOKIES_FILE} \
    -O- | grep -m 1 -o -e "token=[0-9a-zA-Z]*" | head -1 | cut -d"=" -f2)
    
    #TOKEN=$(curl ${BASE_URL} -s -k -u "${USERNAME}":"${PASSWORD}" -c ${COOKIES_FILE} \
    #-o - | grep -m 1 -o -e "token=[0-9a-zA-Z]*" | head -1 | cut -d'=' -f2)
    
    # Token Check
    if [ ${#TOKEN} != 32 ]; then
        LOG ${LINENO} "[ERROR] Token Error !! (${TOKEN})"
        exit -1
    fi
    
    LOG ${LINENO} "[INFO] Token : ${TOKEN}"
    
    # --------------------------------------
    # Sync
    # --------------------------------------
    for TMP_DB in ${DBLIST}; do
    
        OUTFILE=${TMP_DB}.sql
        OUTFILEPATH=${OUTFOLDERPATH}/${OUTFILE}
    
        LOG ${LINENO} "DATABASE:[${TMP_DB}] OUTFILEPATH:[${OUTFILEPATH}]"
    
        wget \
        ${EXPORT_URL} \
        --quiet \
        --no-check-certificate \
        --auth-no-challenge \
        --http-user=${USERNAME} --http-passwd=${PASSWORD} \
        --keep-session-cookies \
        --load-cookies=${COOKIES_FILE} \
        --post-data="token=${TOKEN}&export_type=server&export_method=quick&quick_or_custom=custom&db_select%5B%5D=${TMP_DB}&output_format=sendit&filename_template=%40SERVER%40&remember_template=on&charset_of_file=utf-8&compression=none&what=sql&pdf_report_title&pdf_structure_or_data=data&excel_null=NULL&excel_edition=win&excel_structure_or_data=data&latex_caption=something&latex_structure_or_data=structure_and_data&latex_structure_caption=%A5%C6%A1%BC%A5%D6%A5%EB+%40TABLE%40+%A4%CE%B9%BD%C2%A4&latex_structure_continued_caption=%A5%C6%A1%BC%A5%D6%A5%EB+%40TABLE%40+%A4%CE%B9%BD%C2%A4+%28%C2%B3%A4%AD%29&latex_structure_label=tab%3A%40TABLE%40-structure&latex_comments=something&latex_columns=something&latex_data_caption=%A5%C6%A1%BC%A5%D6%A5%EB+%40TABLE%40+%A4%CE%C6%E2%CD%C6&latex_data_continued_caption=%A5%C6%A1%BC%A5%D6%A5%EB+%40TABLE%40+%A4%CE%C6%E2%CD%C6+%28%C2%B3%A4%AD%29&latex_data_label=tab%3A%40TABLE%40-data&latex_null=%5Ctextit%7BNULL%7D&phparray_structure_or_data=data&sql_include_comments=something&sql_header_comment&sql_compatibility=NONE&sql_structure_or_data=structure_and_data&sql_procedure_function=something&sql_create_table_statements=something&sql_if_not_exists=something&sql_auto_increment=something&sql_backquotes=something&sql_type=INSERT&sql_insert_syntax=both&sql_max_query_size=50000&sql_hex_for_blob=something&sql_utc_time=something&mediawiki_structure_or_data=data&mediawiki_caption=something&mediawiki_headers=something&yaml_structure_or_data=data&csv_separator=%2C&csv_enclosed=%22&csv_escaped=%22&csv_terminated=AUTO&csv_null=NULL&csv_structure_or_data=data&ods_null=NULL&ods_structure_or_data=data&codegen_structure_or_data=data&codegen_format=0&json_structure_or_data=data&texytext_structure_or_data=structure_and_data&texytext_null=NULL&odt_structure_or_data=structure_and_data&odt_comments=something&odt_columns=something&odt_null=NULL&htmlword_structure_or_data=structure_and_data&htmlword_null=NULL&knjenc=" \
        -O ${OUTFILEPATH}
    
    done
    
    # --------------------------------------
    # Mail Send
    # --------------------------------------
    host="[メールサーバ]"
    port="[メールサーバのポート番号]"
    user="[メールユーザー]"
    pass="[メールパスワード]"
    to="[送信先メールアドレス]"
    from="[送信元メールアドレス]"
    
    find ${OUTFOLDERPATH} -daystart -mtime -1 -ls > ${mypath}/${myname}.txt
    
    date_e=`date +'%Y/%m/%d %H:%M:%S'`
    
    function mail_input {
      echo "EHLO localhost"
      sleep 1
      echo "auth login"
      echo $user
      echo $pass
      echo "mail from: $from"
      echo "rcpt to: $to"
      echo "data"
      echo "from: $from"
      echo "to: $to"
      echo "subject: phpMyAdmin Export - Complete (XXXX)"
      echo ""
      echo "${date_s} - ${date_e}"
      echo ""
      grep "${mydate}" "${mypath}/${myname}.log"
      echo ""
      echo "----"
      cat ${mypath}/${myname}.txt
      echo ""
      echo "."
      echo "quit"
    }
    
    # send
    mail_input | nc $host $port
    
    # ------------------------------------------------------------------------------
    # Program End
    # ------------------------------------------------------------------------------
    
    LOG ${LINENO} "<<<<<<<< Program End >>>>>>>>"
    
    # ---1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----
    ```
<br>
1. プログラムの動作としては、以下の様な感じです。
    1. phpMyAdmin にログインする。　※トークン情報の取得
    2. 出力する DB のリストを順々にエクスポートする。
    3. 結果をメールで通知する。
<br><br>
1. 以下は、phpMyAdmin 絡みの情報ですので、設定して下さい。
<br>
    * BASE_URL の最後は、/ 付けて下さい。
    * DBLIST は、出力する DB 名を一行ずつ記載して下さい。

    ```bash
    USERNAME="[phpMyAdmin へのログインユーザー]"
    PASSWORD="[phpMyAdmin へのログインパスワード]"
    COOKIES_FILE="${mypath}/${myname}.tmp"
    BASE_URL="[phpMyAdmin の URL]"
    EXPORT_URL="${BASE_URL}export.php"
    
    OUTFOLDERPATH="[出力先フォルダ]"
    
    DBLIST="
    [出力する DB のリスト (※一行ずつ)]
    "
    ```
<br>
1. DB の出力形式を変更したいのであれば、以下の行(104行目)を変更して下さい。

    ブラウザからエクスポートする時の出力形式の設定と同じ(パラメータと対応)なので、
    頑張ってみて下さい。

    ```bash
    --post-data="token=${TOKEN}&〜
    ```
<br>
1. 以下は、メール絡みの情報ですので、設定して下さい。

    ```bash
    host="[メールサーバ]"
    port="[メールサーバのポート番号]"
    user="[メールユーザー]"
    pass="[メールパスワード]"
    to="[送信先メールアドレス]"
    from="[送信元メールアドレス]"
    ```
<br>
1. 以下は、送信メールを作成してるところです。

    メールのタイトルや本文を変えたいのであれば、
    `echo "subject: phpMyAdmin Export - Complete (XXXX)"`
    以降を修正してもらえればいいかと思います。

    ```bash
    find ${OUTFOLDERPATH} -daystart -mtime -1 -ls > ${mypath}/${myname}.txt
    
    date_e=`date +'%Y/%m/%d %H:%M:%S'`
    
    function mail_input {
      echo "EHLO localhost"
      sleep 1
      echo "auth login"
      echo $user
      echo $pass
      echo "mail from: $from"
      echo "rcpt to: $to"
      echo "data"
      echo "from: $from"
      echo "to: $to"
      echo "subject: phpMyAdmin Export - Complete (XXXX)"
      echo ""
      echo "${date_s} - ${date_e}"
      echo ""
      grep "${mydate}" "${mypath}/${myname}.log"
      echo ""
      echo "----"
      cat ${mypath}/${myname}.txt
      echo ""
      echo "."
      echo "quit"
    }
    ```

# ９９．ハマりポイント

* 今回は、かなりハマりました…。悔しいッ!!
<br><br>
* 最初、自分のパソコンでコマンドを打ちつつ確認していたんですが、サーバから実行すると、403 になってしまって、どういうことか全然わからなくて、コマンドのパラメータを変えたり色々やってたら、最終的に共用サーバ側で IP アドレス規制をかけていることが分かって、「もうッ!!そりゃ無理だよねッ!!」ってなって、「もうッ、これまで悩んだ時間を返してよーッ!!」って…。全部 AWS に移して欲しい…。共用サーバとか、ホントもう嫌ッ!!
<br><br>
* で、その後は、エクスポートでハマりました。
<br><br>
* ログインは通って、トークン情報を取得できるんだけど、エクスポートがどうしてもできない。仕方がないので、また色々とコマンドのパラメータを変更するもうまくいかず…。で、ブラウザでのエクスポートの動作と一つずつ確認していったところ、エクスポートの時にも
`--http-user=${USERNAME} --http-passwd=${PASSWORD}` を付けないといけないことがようやく分かって、なんとかうまくいきました…。
<br><br>
* 疲れた…。

# ＸＸ．まとめ

そもそも、wget とか、curl とか、ウェブのこととか、あまり理解出来ていない私がいけないことは百も承知ではあるんですが…、非常に悔しい…。

勉強せんとね…。

で、
参考にしたサイトはこちら。
バージョンや設定によっては、ログイン認証が POST の場合もあるみたいなので、
うまくいかないときは、その辺りを確認するものいいかもしれません。

* [automation \- How to export one database from phpmyadmin with wget \- Stack Overflow](https://stackoverflow.com/questions/23117733/how-to-export-one-database-from-phpmyadmin-with-wget)
* [automation \- How can I automate the exportation of a mySQL database using phpMyAdmin \- Stack Overflow](https://stackoverflow.com/questions/9945995/how-can-i-automate-the-exportation-of-a-mysql-database-using-phpmyadmin)
* [pierre\.fritsch\.free\.fr/backup/save\_sql\_phpmyadmin\_v1](http://pierre.fritsch.free.fr/backup/save_sql_phpmyadmin_v1)
* [Scripting mysql database backups on phpMyadmin with CURL – WebLog Pro Olivier Berger](https://www-public.tem-tsp.eu/~berger_o/weblog/2007/05/29/scripting-mysql-database-backups-on-phpmyadmin-with-curl/)