はじめに
以下のようなエラーが発生する事がある
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2 "No such file or directory")
原因
mysqlが立ち上がっていない事が多い。
CentOS7の場合は起動する
systemctl start mysql
以下のようなエラーが発生する事がある
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2 "No such file or directory")
mysqlが立ち上がっていない事が多い。
CentOS7の場合は起動する
systemctl start mysql
DynamoDBを操作するとき、DQLの操作が難しかったり、GroupByができなかったり。SQLでできないところができなかったりすることが多い。redashを使えばそれもなんとかなったりします。
redashにはQeury Resultsという機能があります(2018/10現在、ベータ版)。これは取得したクエリに対し、SQLを用いてデータを結合させたり、編集することができる機能です。
一度DQLの結果をredashのQuery Resultsを経由させることで細かいところに手が届くようになります。
Query Resultを指定し、redashで以下のようなクエリを書きます
select *, sum(price) from query_123 group by userID
もちろんDQLのみならず、他の言語も似たようにQuery Resultをかえすことで編集可能です。
OSS版のMarketoのようなマーケティングツールを使いたいとマーケティングチームから話が上がってきたが、Dockerでインストールを試みたが一筋縄に行かなかった。
https://qiita.com/kooooooooooooooooohe/items/43f9452acc539dbd3083
を参考にdocker-composeで立ち上げ、ブラウザでinstallしようとする。
するとこの画面でSQL Syntaxエラーが発生。
An error occurred while attempting to install the data: An exception occurred while executing 'CREATE TABLE reports (id INT AUTO_INCREMENT NOT NULL, is_published TINYINT(1) NOT NULL, date_added DATETIME DEFAULT NULL, created_by INT DEFAULT NULL, created_by_user VARCHAR(255) DEFAULT NULL, date_modified DATETIME DEFAULT NULL, modified_by INT DEFAULT NULL, modified_by_user VARCHAR(255) DEFAULT NULL, checked_out DATETIME DEFAULT NULL, checked_out_by INT DEFAULT NULL, checked_out_by_user VARCHAR(255) DEFAULT NULL, name VARCHAR(255) NOT NULL, description LONGTEXT DEFAULT NULL, system TINYINT(1) NOT NULL, source VARCHAR(255) NOT NULL, columns LONGTEXT DEFAULT NULL COMMENT '(DC2Type:array)', filters LONGTEXT DEFAULT NULL COMMENT '(DC2Type:array)', table_order LONGTEXT DEFAULT NULL COMMENT '(DC2Type:array)', graphs LONGTEXT DEFAULT NULL COMMENT '(DC2Type:array)', group_by LONGTEXT DEFAULT NULL COMMENT '(DC2Type:array)', aggregators LONGTEXT DEFAULT NULL COMMENT '(DC2Type:array)', settings LONGTEXT DEFAULT NULL COMMENT '(DC2Type:json_array)', is_scheduled TINYINT(1) NOT NULL, schedule_unit VARCHAR(255) DEFAULT NULL, to_address VARCHAR(255) DEFAULT NULL, schedule_day VARCHAR(255) DEFAULT NULL, schedule_month_frequency VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB': SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'system TINYINT(1) NOT NULL, source VARCHAR(255) NOT NULL, columns LONGTEXT DEFAU' at line 1
ソースを読んで直そうと試みたが、実運用ではなくちょっと試したいという温度感のようだったので、Dockerを諦め、とりあえず最短で使える方法を選んだ。
Dockerを諦めた。以下のQiitaの記事のコピペでinstallができる。
https://qiita.com/bezeklik/items/3cd61156367909e31421
CloudWatch Logsで集めたログの中で任意の文字列(例えば、Errorとか、Criticalとか)が記載されていた場合、メールなどで通知させたい事がある。
Node.jsをLambdaで動かす事で文字列監視を実装した。
まずはSNSでメールの宛先から作成しARNを控え、エンドポイントとなるメールアドレスを設定する。
関数コードを編集
ERROR、CRITICALという文字列があったら監視するスクリプト
var zlib = require('zlib'); var aws = require('aws-sdk'); var sns = new aws.SNS({ region: 'ap-northeast-1' }); exports.handler = function(input, context, callback) { var data = new Buffer(input.awslogs.data, 'base64'); zlib.gunzip(data, function(e, rst) { if (e) { callback(e); } else { rst = JSON.parse(rst.toString('utf-8')); var errL = rst['logEvents'] .filter(function(evt) { return evt['message'].match(/ERROR/i) ;}) .filter(function(evt) { return !evt['message'].match(/$^/) ;}) .map(function(evt) { return evt['message'] }); console.log('processing[Error]' + errL.length + '/' + rst['logEvents'].length + ' events.'); var critL = rst['logEvents'] .filter(function(evt) { return evt['message'].match(/CRITICAL/i) ;}) .filter(function(evt) { return !evt['message'].match(/$^/) ;}) .map(function(evt) { return evt['message'] }); console.log('processing[Crit]' + critL.length + '/' + rst['logEvents'].length + ' events.'); if (errL.length === 0 && critL.length === 0) { callback(); return; } var date = new Date(); date.setTime(date.getTime() + 1000*60*60*9); var dateTime = date.getFullYear() + '/' + ("0" + (date.getMonth() + 1)).slice(-2) + '/' + ("0" + date.getDate()).slice(-2) + ' ' + ("0" + date.getHours()).slice(-2) + ':' + ("0" + date.getMinutes()).slice(-2) + ':' + ("0" + date.getSeconds()).slice(-2); if (0 < errL.length) { // has error log var sjct = '[Error] Notify From CloudWatch Logs'; var pl = { default: '' }; pl['default'] += 'NotifyAt: ' + dateTime.valueOf() + '\n'; pl['default'] += 'Log: ' + rst['logGroup'] + ' - ' + rst['logStream'] + '\n'; pl['default'] += 'Filter: ' + rst['subscriptionFilters'] + '\n'; pl['default'] += 'Messages:\n'; pl['default'] += errL.join('\n---\n'); sns.publish({ Subject: sjct, Message: JSON.stringify(pl), MessageStructure: 'json', TargetArn: 'arn:aws:sns:ap-northeast-1:1234567890(your no):(your arn)' }, function(err, data) { if (err) { callback(err); } else if (0 < critL.length) { // has waring too var sjct = '[Critical] Notify From CloudWatch Logs'; var pl = { default: '' }; pl['default'] += 'NotifyAt: ' + dateTime.valueOf() + '\n'; pl['default'] += 'Log: ' + rst['logGroup'] + ' - ' + rst['logStream'] + '\n'; pl['default'] += 'Filter: ' + rst['subscriptionFilters'] + '\n'; pl['default'] += 'Messages:\n'; pl['default'] += critL.join('\n---\n'); sns.publish({ Subject: sjct, Message: JSON.stringify(pl), MessageStructure: 'json', TargetArn: 'arn:aws:sns:ap-northeast-1:1234567890(your no):(your arn)' }, function(err, data) { if (err) callback(err); else callback(null, data); }); } else { callback(null, data); } }); } else { // has NOT error log == criticaling only var sjct = '[Critical] Notify From CloudWatch Logs'; var pl = { default: '' }; pl['default'] += 'NotifyAt: ' + dateTime.valueOf() + '\n'; pl['default'] += 'Log: ' + rst['logGroup'] + ' - ' + rst['logStream'] + '\n'; pl['default'] += 'Filter: ' + rst['subscriptionFilters'] + '\n'; pl['default'] += 'Messages:\n'; pl['default'] += critL.join('\n---\n'); sns.publish({ Subject: sjct, Message: JSON.stringify(pl), MessageStructure: 'json', TargetArn: 'arn:aws:sns:ap-northeast-1:1234567890(your no):(your arn)' }, function(err, data) { if (err) callback(err); else callback(null, data); }); } } }); };
今回はCloudWatch Logsがトリガーとなるので、CloudWatch Logsを選択し、その後対象のログを選択する。
Amazon SNSのARNを選択する(予めSNSでトピックを作っておく必要がある)
以上
DynamoDBは言わずと知れたKVSだが、それを忘れてredashで実行しようとすると、当然ながらエラーになる。
redashでDynamoDBのデータを見ようとした際、以下のようなエラーが出た
Error running query: No index found for query. Please use a SCAN query, or set allow_select_scan=True opt allow_select_scan true Download Dataset
AWSでcloudwatchで監視し、異常があったらSNSで通知する事はあるが、SNSではデフォルトで「配信停止(unsubscribe)する場合は、ここクリックしてね」とありがたいことに(?)記載されてある。
チーム開発しているとSNSの通知先がメーリングリストにしていると、誤って押されてしまうと、その後のメールが来なくなってしまう。
配信停止(unsubscribe)を押された場合検知はさっくり作れたのでそれをまとめる
awsコマンドとjqコマンドをうまく組み合わせる
aws sns list-subscriptions | jq -r '.Subscriptions[] | select(.SubscriptionArn == "Deleted") '
結果
aws sns list-subscriptions | jq -r '.Subscriptions[] | select(.SubscriptionArn == "Deleted") ' { "SubscriptionArn": "Deleted", "Owner": "xxxxxxxxxx", "Protocol": "email", "Endpoint": "sute@sumito.jp", "TopicArn": "arn:aws:sns:ap-northeast-1:xxxxxxx:xxxxxxxxx" }
unsubscribeされたメールドレスや、TopicArn情報などを確認することができる。
ちなみにチャットワークに通知する場合は以下の通りシェルでラップする
#!/bin/bash aws --profile=$1 sns list-subscriptions | jq -r '.Subscriptions[] | select(.SubscriptionArn == "Deleted") ' > /tmp/check-unsubscribe.$1 # 文字を整形する # headder cat << _EOT_ > /tmp/check-unsubscribe.$1.txt [info] [title]Someone clicked unsubscribe link [/title] _EOT_ # contents cat /tmp/check-unsubscribe.$1 >> /tmp/check-unsubscribe.$1.txt echo "[/info]" >> /tmp/check-unsubscribe.$1.txt _roomid=xxxxxxxxxxxxx # (your chatroom id) _body=`cat /tmp/check-unsubscribe.$1.txt` # 1件以上あれば通知する if [ `wc -l /tmp/check-unsubscribe.$1 | awk '{print $1}'` -gt 0 ] ; then curl -X POST -H "X-ChatWorkToken: 123456789" -d "body=${_body}" "https://api.chatwork.com/v2/rooms/${_roomid}/messages" fi exit 0
ymlファイルをCloudFormationでデプロイした時、というエラーが出た。
When yml file is deployed with CloudFormation, bellow error was happened.
ZipFile length cannot exceed 4096 characters. For larger source use S3Bucket/S3Key properties instead.
zip化する際に含まれるコードが4096文字を越えると本エラーに陥る。
This error occurs when the code included in zipping exceeds 4096 characters.
いらないところを削除するなどして、コードをコンパクトにする。
Make the code more compact by deleting unnecessary parts.
データ解析するにあたり、BigQueryを使いたい事がある。mysqlからデータを取得するところをembulkを使う。embulkのインストール方法から簡単な使い方までまとめた。
embulkはJavaで作られており、一からinstallしようとすると、割と面倒。今回はDockerを使うこととする。
APIs & Servicesでcredentialを作成する。
jsonファイルダウンロードできるので、適宜保存する。
GCPにプロジェクトを作り、bigqueryに権限を付与。APIで操作できるようjsonファイルを取得する。
FROM java:7 MAINTAINER sumito.tsukada "tsukada@sumito.jp" ENV EMBULK_VERSION 0.8.39 RUN curl -L https://bintray.com/artifact/download/embulk/maven/embulk-${EMBULK_VERSION}.jar -o /opt/embulk.jar RUN java -jar /opt/embulk.jar gem install embulk-input-mysql RUN java -jar /opt/embulk.jar gem install embulk-output-bigquery WORKDIR /work ENTRYPOINT ["java", "-jar", "/opt/embulk.jar"] CMD ["--help"]
build
# docker build -t tsukada/embulk . Sending build context to Docker daemon 2.048kB Step 1/9 : FROM java:7 ---> 5dc48a6b75af Step 2/9 : MAINTAINER sumito.tsukada "tsukada@sumito.jp" ---> Using cache ---> bc78ed50d614 Step 3/9 : ENV EMBULK_VERSION 0.8.39 ---> Using cache ---> 266476a95a55 Step 4/9 : RUN curl -L https://bintray.com/artifact/download/embulk/maven/embulk-${EMBULK_VERSION}.jar -o /opt/embulk.jar ---> Using cache ---> b21e71d6ce44 Step 5/9 : RUN java -jar /opt/embulk.jar gem install embulk-input-mysql ---> Using cache ---> 2fb224b24c49 Step 6/9 : RUN java -jar /opt/embulk.jar gem install embulk-output-bigquery ---> Running in b27f12583137 2018-09-18 02:50:32.526 +0000: Embulk v0.8.39 ********************************** INFORMATION ********************************** Join us! Embulk-announce mailing list is up for IMPORTANT annoucement such as compatibility-breaking changes and key feature updates. https://groups.google.com/forum/#!forum/embulk-announce ********************************************************************************* Gem plugin path is: /root/.embulk/jruby/2.3.0 Successfully installed uber-0.1.0 Successfully installed declarative-0.0.10 Successfully installed declarative-option-0.1.0 Successfully installed representable-3.0.4 Successfully installed retriable-3.1.2 Successfully installed public_suffix-3.0.3 Successfully installed addressable-2.5.2 Successfully installed mime-types-data-3.2018.0812 Successfully installed mime-types-3.2.2 Successfully installed multipart-post-2.0.0 Successfully installed faraday-0.15.2 Successfully installed multi_json-1.13.1 Successfully installed jwt-2.1.0 Successfully installed signet-0.9.2 Successfully installed memoist-0.16.0 Successfully installed os-1.0.0 Successfully installed googleauth-0.6.6 Successfully installed httpclient-2.8.3 Successfully installed google-api-client-0.24.0 Successfully installed thread_safe-0.3.6-java Successfully installed tzinfo-1.2.5 Successfully installed time_with_zone-0.3.1 Successfully installed embulk-output-bigquery-0.4.9 23 gems installed ---> 74e55d0084d6 Removing intermediate container b27f12583137 Step 7/9 : WORKDIR /work ---> 19d9c56bf738 Removing intermediate container c73ef21e7b6c Step 8/9 : ENTRYPOINT java -jar /opt/embulk.jar ---> Running in 4bca2f2ed68e ---> b4458584af6f Removing intermediate container 4bca2f2ed68e Step 9/9 : CMD --help ---> Running in 7fdbd68d5021 ---> 0bfdab6b8d24 Removing intermediate container 7fdbd68d5021 Successfully built 0bfdab6b8d24 Successfully tagged tsukada/embulk:latest
今回はmysqlからデータを抜き、BigQueryに入れるとする。
in: type: mysql user: redash password: passwd database: sample host: 127.0.0.1 query: "select date, user from sampletable" out: type: bigquery auth_method: json_key json_keyfile: tsukada-bigquery.json path_prefix: /tmp/ file_ext: .csv.gz source_format: CSV project: 12345679 dataset: table123 auto_create_table: true table: user_data formatter: {type: csv, charset: UTF-8, delimiter: ',', header_line: false} encoders: - {type: gzip}
実行
docker run -t -v ${PWD}:/work tsukada/embulk run sample.yml
以下のようい表示されればOK
[INFO] (main): Committed.
データが入ったという事がわかった。
また、
#standardSQL
と書いてあるが、これはコメントではなく、BigQueryが判断する重要な宣言になるので削除するとうまく動かないので注意。
先ほど使ったjsonファイルと接続先のプロジェクトIDを入力すると、redashからbigqueryへ接続する事ができる。
一定の容量のあるただのファイルを作成したいことがたまにある。例えばwordpressのupload容量を変更した際の動作テストを行ったりとかが一例。linuxのみならずmacでもddコマンドで簡単に作成することができるのでその方法を紹介。
linuxもmacも共通の手順はこちら(macで実施した際のログ)
$ dd if=/dev/zero of=~/80M bs=1 count=83886080 83886080+0 records in 83886080+0 records out 83886080 bytes transferred in 189.533890 secs (442591 bytes/sec) $
80Mの空ファイルが作成される。中身は/dev/zeroなので、からっぽ。
上記例ではcountはバイト単位になる。
* 1024 * 1024 * 80 = 83886080
で80MByteという計算。
ただし、189.533890 secs とあるように、3分以上かかっている。
これは1回に読み書きするブロックサイズ(bsオプション)が1になっているため。
この値を1 -> 1024に変更すれば理論上は1024倍高速になる。
$ dd if=/dev/zero of=~/80M_1024 bs=1024 count=81920 81920+0 records in 81920+0 records out 83886080 bytes transferred in 0.375389 secs (223464489 bytes/sec) $
作成されたファイルは同じく80Mだが、0.375389 secsで完了した。
bsが1の時と、1024の結果を比較した結果、504倍高速になったが、理論上の1024倍には届かなかった(残念だがそうゆうもんだ。。)。
実はddで送った結果を直接他のサーバに送りつけることもできる。
dd if=/dev/sda | ssh root@転送先サーバ " dd of=/転送先ディレクトリ/server.sda.img"
DISKの中身を強制的にddコマンドで吸い上げ、他のサーバにイメージとして保存することもできる。今はDocker含むコンテナ全盛期の時代だが、KVMなどを使えば、吸い上げたイメージを元に仮想サーバとして動かすこともできる。
参考記事
https://qiita.com/S-T/items/8de3c150c7097bd021fa
データベースを可視化するのにredashはとても便利。
しかし、運用を考えるといろいろ考えることがある。
redashでよく使うオペレーションをまとめた。
cd ~/redash docker-compose -f docker-compose.production.yml up -d
docker exec -it redash_server_1 ./manage.py users list
docker exec -it redash_server_1 ./manage.py users create sumito.tsukada@sumito.jp sumito.tsukada
docker exec -it redash_server_1 ./manage.py users password sumito.tsukada@sumito.jp password
docker exec -it redash_server_1 ./manage.py users deletesumito.tsukada@sumito.jp
redash v5以前は、userをdisableする機能がなかったので削除するしかなかったが、一度クエリを作ったり、ダッシュボードを作ると削除できないという問題があった。v5以降は標準でdisableする機能が追加されたので今後使う頻度は減りそう。
v4以前で上記コマンドでエラーになった場合、redash_postgres_1のレコードを強制的に削除することによって削除が可能になる(ことがある)
docker ps (login to postgress) docker exec -it redash_postgres_1 /bin/bash psql -U postgres postgres SELECT * FROM events WHERE user_id = 6; DELETE FROM events WHERE user_id = 6;
docker ps docker exec -it redash_postgres_1 /bin/bash pg_dump -U postgres postgres | gzip > /tmp/redash_backup.gz exit docker cp redash_postgres_1:/tmp/redash_backup.gz .
本作業を行う前に、postgres以外のdockerコンテナを停止する
docker cp /tmp/redash_backup.gz redash_postgres_1:/tmp/redash_backup.gz docker exec -it redash_postgres_1 /bin/bash psql -U postgres template1 DROP DATABASE IF EXISTS postgres; CREATE DATABASE postgres; \q zcat /tmp/redash_backup.gz | psql -U postgres -d postgres
cronなのに仕込み、定期的に取得する
/bin/docker exec redash_postgres_1 pg_dump -U postgres postgres | /bin/gzip > /tmp/redash_backup.gz
オライリー本より読みやすく、Dockerについて体系的に学ぶことができるのでおすすめ。
![]() |