第 7 回 kintone コマンドラインツール(cli-kintone v0)のバックアップ処理をシェルスクリプトにしてみよう

著者名: 瀧ヶ平 充 (External link)

目次

information

このチュートリアルは ver. 0.x.x の cli-kintone の使い方を紹介しています。
ver.1.0.0 以降の cli-kintone の使い方を紹介するチュートリアルは次のページを参照してください。
はじめよう cli-kintone

はじめに

こんにちは、今回は第 6 回で触れた別ドメインへのバックアップ処理をシェルスクリプトにしていこうと思います。
コマンドライン操作に慣れた方向けの内容となるため、少し難しくなるかと思います。

今回は UNIX 系 OS で使われているシェルのひとつ Bash を前提として行うため、Windows ユーザの方は Cygwin などの Bash が利用できる環境を用意してください。

シェルスクリプトとは

コマンドで逐次実行していた処理をまとめて記述したものです。
定型化された処理の自動化などに向いています。
1 つずつ処理を積み重ねて書くことで、一連の処理が一度の実行で済むようにできるので便利です。

作成方法

基本的には、実行したい処理を一定のルールにしたがってテキストファイルへ書き込んでいくだけです。
ただし、そのままだと実行できないので、作成したファイルに実行権限を付与すると完成です。

サンプルの作成

「Hello!」と表示するだけの簡単なサンプルで、シェルスクリプトの概要をつかんでみましょう。
「greeting.sh」というファイル名で空のテキストファイルを作成して、そこに次の 2 行を書き込んでください。

1
2
#!/bin/bash
echo 'Hello!'

サンプルの実行

作成したファイルと同階層にいることを確認したら、次の要領でファイルを指定して実行してみましょう。

1
./greeting.sh

おそらく、次のようなエラーが表示されたのではないでしょうか。

1
2
3
./greeting.sh

-bash: ./greeting.sh: Permission denied

これは、指定したファイルを実行する権限がないことで発生したエラーです。
今後作成するシェルスクリプトでも同様のエラーが発生するかもしれませんが、これはファイルの権限の問題です。 次のコマンドで、ファイルに実行権限を付与して対処します。

1
chmod +x ./greeting.sh

上記コマンドを実行したら、作成したシェルスクリプトを再度実行してみましょう。

1
2
3
./greeting.sh

Hello!

今回は上記のように「Hello!」と表示されたのではないでしょうか。

シェルスクリプトの書き方

上記サンプルでは指定したコマンドをひとつ実行しただけでしたが、もう少し詳細な条件を指定して作成できます。
以下、シェルスクリプトの書き方をみていきましょう。

shebang の宣言

1
#!/bin/bash

これは shebang(シェバン)と言って、シェルスクリプトを実行するインタプリタ(シェルなど)を指定する部分です。
ここで Bash のパスを指定することで、Bash を用いてこのスクリプトを実行することを宣言しています。
シェルスクリプトではこの宣言を一行目に書いて、その次の行から実行するコマンドを書いていきます。

変数

シェルスクリプトおよびシェル上では、一時的な変数を宣言して処理に利用できます。

1
variable_name='hoge'

上の例では variable_namehoge という値を代入しています。
実際に利用する際は、次のように $variable_name と表記して使います。

1
echo $variable_name

シェルでは $variable_name に代入されている値、ここでは「hoge」と評価してからコマンドを実行します。
つまり、実際には次のコマンドが実行されるのと同じになります。

1
echo hoge

パイプライン処理

POSIX に準拠したコマンドは、あるコマンドの実行結果を引きついで別のコマンドを実行する機能を持っています。
POSIX とは、UNIX 系 OS などの API に関する IEEE が策定した規格のことです。

| の左側で指定したコマンドの出力は、その右側で指定したコマンドの入力として扱われます。
たとえば、 grep は指定した文字列が含まれる行を抽出できるコマンドです。
以下のように使うことで、cli-kintone でエクスポートされた CSV データの中から「HOGE」を含む行を抽出できます。

1
cli-kintone --export -a <アプリID> -d <ドメイン名> -t <APIトークン> | grep "HOGE"

コマンド置換

Bash では別のコマンドの実行結果をコマンドの引数にできます。

たとえば、 cat は指定した入力の中身をそのまま出力するコマンドです。
cat コマンドで取り出された「foo.txt」の中身を変数に格納したい場合、以下のようにすると実現できます。

1
foo=$(cat foo.txt)

if 文(分岐処理)

Bash 上でも if を使った分岐処理ができます。

変数 $a が 0 だった場合は「F」、それ以外の場合は「T」を出力というように処理を分岐させたい場合は、以下のように書きます。

1
2
3
4
5
if [ $a -eq 0 ]; then
  echo F
else
  echo T
fi

バックアップ用シェルスクリプトの作成

ここからは、前回紹介したバックアップ処理を実行するシェルスクリプトの作成に取りかかります。

前回のバックアップ操作は次のような流れでした。

  1. バックアップ元のアプリから CSV をエクスポート
  2. CSV を編集し、1 行目の $id を recordid に置き換える。
  3. CSV をバックアップ先のアプリにインポート

2 回目以降のバックアップと同期は処理が少し変わりますので、まずはこの流れをシェルスクリプトにしていきましょう。

STEP1:変数の準備

まずは、コマンドのパラメーターで使う値を変数に格納してしまいましょう。
こうすることで、複数のパターンのアプリでも変数を変えるだけで対応でき、処理本体に影響なく汎用化させることができますね。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/bin/bash

inputDomain=<バックアップ元アプリのドメイン>
inputApp=<バックアップ元のアプリID>
inputToken=<バックアップ元のAPIトークン>
outputDomain=<バックアップ先アプリのドメイン>
outputApp=<バックアップ先のアプリID>
outputToken=<バックアップ元のAPIトークン>
attachmentDir=<添付ファイルを保存するディレクトリ>
backupFile=backup.csv

今回はバックアップ元を入力、バックアップ先を出力とみなして、このような変数名にしてみました。

STEP2:コマンドの追加

変数が準備できたら、次はコマンドを書いていきましょう。
CSV のエクスポートとバックアップ先へのインポートには、このようなコマンドを実行します。

1
2
3
4
5
# バックアップ元からエクスポート
cli-kintone --export -d $inputDomain -a $inputApp -t $inputToken -b $attachmentDir > $backupFile

# バックアップ先へインポート
cli-kintone --import -d $outputDomain -a $outputApp -t $outputToken -f $backupFile -b $attachmentDir

このコマンドでは「$id」が残ったままになるので、エクスポートされる CSV はそのままインポートできません。
そこで、「$id」を「recordid」に変更するように CSV を編集する必要がありますが、この作業もコマンドを使って対応します。

STEP3:コマンドで文字列を置換

一般に UNIX 系 OS のシェルでは、 sed コマンドを用いて文字列を置換できます。
多くの場合デフォルトでインストールされていますが、ない場合はインストールしてください。

今回は、CSV 一行目の「$id」を「recordid」に置換したいので、以下のような形にバックアップ元からのエクスポート部分を書き換えます。

1
2
# バックアップ元からエクスポート
cli-kintone --export -d $inputDomain -a $inputApp -t $inputToken -b $attachmentDir | sed "1 s/\$id/recordid/" > $backupFile

今回追加したコマンドにある 1 s/\$id/recordid/ という部分ですが、これは 1 行目の「\$id」というパターンに一致する部分を「recordid」に置換する、という命令になります。

sed については以下のコマンドを実行することでも詳しく使い方を見ることができます。

1
man sed

STEP4:実行権限の付与

ここまでの作成したシェルスクリプトの全体は以下のようになります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#!/bin/bash

inputDomain=<バックアップ元アプリのドメイン>
inputApp=<バックアップ元のアプリID>
inputToken=<バックアップ元のAPIトークン>
outputDomain=<バックアップ先アプリのドメイン>
outputApp=<バックアップ先のアプリID>
outputToken=<バックアップ元のAPIトークン>
attachmentDir=<添付ファイルを保存するディレクトリ>
backupFields=<バックアップするフィールド(カンマ区切り)> # ここには必ず $id を含めるようにしてください
backupFile=backup.csv

# バックアップ元からエクスポート
cli-kintone --export -d $inputDomain -a $inputApp -t $inputToken -b $attachmentDir | sed "1 s/\$id/recordid/" > $backupFile

# バックアップ先へインポート
cli-kintone --import -d $outputDomain -a $outputApp -t $outputToken -f $backupFile -b $attachmentDir

これを「kintone-backup.sh」として保存し、以下のコマンドで実行権限を追加してください。

1
chmod +x kintone-backup.sh

これでバックアップ処理が実行できるはずです。

レコード同期用シェルスクリプトの作成

レコード同期の処理では、バックアップ済のレコードの最新の「recordid」を確認し、それを基準に新規レコードのバックアップと既存レコードの同期をしていました。
最新の「recordid」を取得し変数に入れれば、この処理もシェルスクリプト内で完結できます。

STEP1:最新の「recordid」を変数に格納

前回使用したコマンドを実行して recordid を確認すると、そのエクスポート結果は以下のようなフォーマットになっていました。

1
2
"recordid"
"30"

このまま変数に入れるのは難しいので、こちらも sed コマンドで加工します。

1
cli-kintone.exe --export -a $outputApp -d $outputDomain -t $outputToken -c "recordid" -q "order by $id desc limit 1" | sed "1 d"

これで「30」の部分がエクスポートされるようになるので、先に説明した「コマンド置換」でエクスポート結果を変数に格納します。

1
lastRecordId=$(cli-kintone --export a $outputApp -d $outputDomain -t $outputToken -c "recordid" -q "order by $id desc limit 1" | sed "1 d")

これで、変数 $lastRecordId に、バックアップ済みの最新の「recordid」を格納できるようになりました。

しかし、このままではバックアップ済のレコードがない場合に問題となります。
$lastRecordId が空だった場合は「0」を代入するように処理を分岐させます。
シェルスクリプトには以下のように記述することになります。

1
2
3
4
lastRecordId=$(cli-kintone --export -a $outputApp -d $outputDomain -t $outputToken -c "recordid" -q "order by $id desc limit 1" | sed "1 d")
if [ $lastRecordId -eq "" ]; then
  lastRecordId=0
fi

STEP2:レコードをバックアップ・同期する

バックアップは以下のような形でできます。

1
2
3
4
5
6
# 新規にバックアップ
# バックアップ元からエクスポート
cli-kintone --export -d $inputDomain -a $inputApp -t $inputToken -b $attachmentDir -q '\$id > $lastRecordId' | sed "1 s/\$id/recordid/" > $backupFile

# バックアップ先へインポート
cli-kintone --import -d $outputDomain -a $outputApp -t $outputToken -f $backupFile -b $attachmentDir

ここまでで同期用のファイル名を定義していなかったので、新たに変数 $syncFile として同期用のファイル名を代入しておきましょう。
同期は以下のような処理になります。

1
2
3
4
5
6
# レコードの同期
# バックアップ元からエクスポート
cli-kintone --export -d $inputDomain -a $inputApp -t $inputToken -b $attachmentDir -q '\$id <= $lastRecordId' | sed "1 s/\$id/*recordid/" > $syncFile

# バックアップ先へインポート
cli-kintone --import -d $outputDomain -a $outputApp -t $outputToken -f $syncFile -b $attachmentDir

シェルスクリプトの全体

ここまででバックアップ・同期の両方に対応したスクリプトを作成しました。
最後にシェルスクリプトの全体を確認してみましょう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/bash

inputDomain=<バックアップ元アプリのドメイン>
inputApp=<バックアップ元のアプリID>
inputToken=<バックアップ元のAPIトークン>
outputDomain=<バックアップ先アプリのドメイン>
outputApp=<バックアップ先のアプリID>
outputToken=<バックアップ元のAPIトークン>
attachmentDir=<添付ファイルを保存するディレクトリ>
backupFields=<バックアップするフィールド(カンマ区切り)> # ここには必ず $id を含めるようにしてください
backupFile=backup.csv
syncFile=syncFile.csv

# バックアップ済最新のレコードID
lastRecordId=$(cli-kintone --export -a $outputApp -d $outputDomain -t $outputToken -c "recordid" -q "order by $id desc limit 1" | sed "1 d")
if [ $lastRecordId -eq "" ]; then
  lastRecordId=0
fi

# 新規にバックアップ
# バックアップ元からエクスポート
cli-kintone --export -d $inputDomain -a $inputApp -t $inputToken -b $attachmentDir -q '\$id > $lastRecordId' | sed "1 s/\$id/recordid/" > $backupFile

# バックアップ先へインポート
cli-kintone --import -d $outputDomain -a $outputApp -t $outputToken -f $backupFile -b $attachmentDir

# レコードの同期
# バックアップ元からエクスポート
cli-kintone --export -d $inputDomain -a $inputApp -t $inputToken -b $attachmentDir -q '\$id <= $lastRecordId' | sed "1 s/\$id/*recordid/" > $syncFile

# バックアップ先へインポート
cli-kintone --import -d $outputDomain -a $outputApp -t $outputToken -f $syncFile -b $attachmentDir

先に説明したときと同様、作成したファイルを保存し、実行権限を付与することで、シェルスクリプトでのバックアップと同期が可能になります。

まとめ

シェルスクリプトの作成、いかがでしたか?
次回はこのシェルスクリプトを自動化する部分についてやっていきます。

information

この Tips は、cli-kintone Ver 0.10.2 と 2020 年 3 月版 kintone で動作を確認しています。