vague memory

うろ覚えを無くしていこうともがき苦しむ人の備忘録

AWS Cloudwatch UIアップデート

いつの間にかCloudWatchのUIが更新されてました。
公式情報は見つけられなかったのですが、気付いたのは3点です。

f:id:htnosm:20160218000613p:plain

目盛軸の範囲設定

縦軸の目盛の範囲を指定できるようになっています。

f:id:htnosm:20160218000612p:plain

軸切替方法の変更

以前はドラック&ドロップで移動していましたが、詳細窓で設定変更するように変わりました。
詳細窓の表示の仕方が少々判り難かったのですが、マウスオーバーで出せます。
表示後に shift キー押下で非表示にできます。

  • 詳細窓を表示

f:id:htnosm:20160218000614p:plain

  • 軸の切替

f:id:htnosm:20160218000610p:plain

系列の表示/非表示切替

凡例部分のクリックで系列の表示/非表示切替ができます。(以前からできたかもしれません)

  • 選択系列のみ表示(他系列を非表示)

f:id:htnosm:20160218000609p:plain

  • 選択系列のみ非表示

f:id:htnosm:20160218000608p:plain


個人的に目盛軸設定できるようになったのはうれしく思います。

Ubuntu 旧バージョンでのサービス起動/停止はserviceコマンドで。

知ってる人には当たり前なのでしょうが、 無知な自分は小一時間ハマりました。
最近はsystemdがデフォルトになってきているので、古いバージョンでの話です。

f:id:htnosm:20160216050523j:plain

各種サービスの起動/停止にはrcスクリプトではなく、 serviceコマンドを使いましょう。
常日頃serviceコマンドで起動/停止しているならば発生しない問題でもあります。
癖でrcスクリプトで実行しがちな自分用備忘録です。

  • 誤:/etc/init.d/service_name start
  • 正:service service_name start

以上です。


経緯

赤い帽子(とせんとくん)歴はそれなりにありましたが、 ほぼ初Ubuntuで /etc/init.d/* スクリプトを使用したサービス起動/停止が行えませんでした。

検証

実際にどうして動作しないのかを確認しました。

環境

$ cat /etc/*release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS"
NAME="Ubuntu"
VERSION="14.04.3 LTS, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04.3 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"

serviceコマンドでの起動/停止

sshの起動/停止を実行します。 正常に動作(起動/停止)します。

起動

# 停止していることを確認
$ ps -ef | grep '[/]usr/sbin/sshd'
$ sudo service ssh status
ssh stop/waiting
# 起動
$ sudo service ssh start
ssh start/running, process 2462
# 起動される
$ ps -ef | grep '[/]usr/sbin/sshd'
root      2462     1  0 18:06 ?        00:00:00 /usr/sbin/sshd -D
$ sudo service ssh status
ssh start/running, process 2462

停止

# 起動していることを確認
$ ps -ef | grep '[/]usr/sbin/sshd'
root      1786     1  0 17:39 ?        00:00:00 /usr/sbin/sshd -D
# 起動していることを確認
$ sudo service ssh status
ssh start/running, process 1786
# 停止
$ sudo service ssh stop
ssh stop/waiting
# 停止される
$ ps -ef | grep '[/]usr/sbin/sshd'
$ sudo service ssh status
ssh stop/waiting

rcコマンドでの起動/停止

sshの起動/停止を実行します。 正常に動作(起動/停止) しません
出力はスクリプトによりまちまちで、失敗(fail)を返してくれる物もありますが、sshは何も出力されません。

起動

# 停止していることを確認
$ ps -ef | grep '[/]usr/sbin/sshd'
# ステータスが取得できない
$ sudo /etc/init.d/ssh status
# 起動
$ sudo /etc/init.d/ssh start
# 起動されない
$ ps -ef | grep '[/]usr/sbin/sshd'
# ステータスが取得できない
$ sudo /etc/init.d/ssh status

停止

# 起動していることを確認
$ ps -ef | grep '[/]usr/sbin/sshd'
root      1786     1  0 17:39 ?        00:00:00 /usr/sbin/sshd -D
# ステータスが取得できない
$ sudo /etc/init.d/ssh status
# 停止
$ sudo /etc/init.d/ssh stop
# 停止されない
$ ps -ef | grep '[/]usr/sbin/sshd'
root      1786     1  0 17:39 ?        00:00:00 /usr/sbin/sshd -D
# ステータスが取得できない
$ sudo /etc/init.d/ssh status

調査

rcスクリプトデバッグ実行

init_is_upstart関数で終了しています。

$ sudo sh -x /etc/init.d/ssh status
・・・略・・・
+ check_for_upstart 1
+ init_is_upstart
+ [ -x /sbin/initctl ]
+ /bin/grep -q upstart
+ /sbin/initctl version
+ return 0
+ exit 1

init_is_upstart関数を実行している箇所がcheck_for_upstart関数となっています。

    36   check_for_upstart() {
    37      if init_is_upstart; then
    38      exit $1
    39      fi
    40  }

呼び出し元を検索すると実行時の引数に関わらず、check_for_upstart関数を実行しています。

$ grep -n -B 1 "check_for_upstart" /etc/init.d/ssh
35-
36:check_for_upstart() {
--
84-  start)
85: check_for_upstart 1
--
96-  stop)
97: check_for_upstart 0
--
106-  reload|force-reload)
107:    check_for_upstart 1
--
118-  restart)
119:    check_for_upstart 1
--
133-  try-restart)
134:    check_for_upstart 1
--
164-  status)
165:    check_for_upstart 1

init_is_upstart関数

/lib/lsb/init-functions に定義されています。

# If the currently running init daemon is upstart, return zero; if the
# calling init script belongs to a package which also provides a native
# upstart job, it should generally exit non-zero in this case.
init_is_upstart()
{
   if [ -x /sbin/initctl ] && /sbin/initctl version 2>/dev/null | /bin/grep -q upstart; then
       return 0
   fi
   return 1
}

upstartを使用している場合は "0" を返すため、 check_for_upstartで必ずexitとなり、スクリプト内後続コマンドが実行されません。

$ /sbin/initctl version
init (upstart 1.12.1)

/etc/init.d/ で init_is_upstart を検索

init_is_upstartが含まれているスクリプトは同じような動作でした。

$ grep -c "init_is_upstart" /etc/init.d/* | grep -v -e ':0$'
/etc/init.d/networking:4
/etc/init.d/rpcbind:3
/etc/init.d/rsyslog:3
/etc/init.d/ssh:1
/etc/init.d/udev:2

思い込みは敵であるということを再認識しました。

SQL 日時列を5秒、30秒単位で集計する

二度と使用する事は無さそうなのですが、 極めて限定的な要件で、RDB上で5秒(30秒)単位で集計する方法です。 (と言っても、日時文字列の末尾を切り捨てているだけです)
環境はRedshiftです。(PostgreSQLでも使えます)
RDBMS用はこちら(SQL 日時列を5秒、30秒単位で集計する(RDBMS別) - Qiita)。

尚、日時データはシステムによって、日付・文字列・数値型と色々な型で格納されますが、 日付型で格納されていることを想定しています。

参照用テーブル例

postgres=# \d TIMESUMTEST
           テーブル "public.timesumtest"
   カラム   |             型              | 修飾語
------------+-----------------------------+--------
 _timestamp | timestamp without time zone |
 _value     | integer                     |

postgres=# select * from TIMESUMTEST LIMIT 10;
     _timestamp      | _value
---------------------+--------
 2016-04-01 17:00:00 |     52
 2016-04-01 17:00:01 |     61
 2016-04-01 17:00:02 |     46
 2016-04-01 17:00:03 |     48
 2016-04-01 17:00:04 |     28
 2016-04-01 17:00:05 |     59
 2016-04-01 17:00:06 |     43
 2016-04-01 17:00:07 |     61
 2016-04-01 17:00:08 |     54
 2016-04-01 17:00:09 |     49
(10 行)

postgres=#

SQL

LEFT関数の方が可読性が良いですが、環境によっては動作しなかったためSUBSTRINGを使用しています。

5秒単位

  • 0〜4秒を5秒、5〜9秒を10(次の0秒)としてグルーピング
SELECT
 CASE /* 5秒単位 */
   -- 0〜4秒はhh:mm:s5
   WHEN SUBSTRING(CAST(_timestamp AS VARCHAR), LENGTH(CAST(_timestamp AS VARCHAR)) - 1 + 1 ,1) <= '4'
     THEN SUBSTRING(CAST(_timestamp AS VARCHAR), 1, 18) || '5'
   -- 5〜9秒はhh:mm:s0
   ELSE SUBSTRING(CAST((_timestamp +INTERVAL '10 SECOND') AS VARCHAR), 1, 18) || '0'
 END AS _timestamp_nsec
,SUM(_value) AS sum_value ,MIN(_value) AS min_value ,MAX(_value) AS max_value ,AVG(_value) AS avg_value
FROM TIMESUMTEST GROUP BY _timestamp_nsec ORDER BY _timestamp_nsec
   _timestamp_nsec   | sum_value | min_value | max_value |      avg_value
---------------------+-----------+-----------+-----------+---------------------
 2016-04-01 17:00:05 |       235 |        28 |        61 | 47.0000000000000000
 2016-04-01 17:00:10 |       266 |        43 |        61 | 53.2000000000000000
 2016-04-01 17:00:15 |       275 |        43 |        63 | 55.0000000000000000
 2016-04-01 17:00:20 |       267 |        42 |        65 | 53.4000000000000000
 2016-04-01 17:00:25 |       247 |        39 |        60 | 49.4000000000000000
 2016-04-01 17:00:30 |       261 |        42 |        59 | 52.2000000000000000
 2016-04-01 17:00:35 |       232 |        39 |        57 | 46.4000000000000000
 2016-04-01 17:00:40 |       311 |        42 |        77 | 62.2000000000000000
 2016-04-01 17:00:45 |       290 |        52 |        66 | 58.0000000000000000
 2016-04-01 17:00:50 |       313 |        53 |        76 | 62.6000000000000000
・・・略

30秒単位

  • 0〜29秒を30秒、30〜59秒を1分(次の00秒)としてグルーピング
SELECT
 CASE /* 30秒単位 */
   -- 00〜29秒はhh:mm:30
   WHEN SUBSTRING(CAST(_timestamp AS VARCHAR), LENGTH(CAST(_timestamp AS VARCHAR)) - 2 + 1 ,2) <= '29'
     THEN SUBSTRING(CAST(_timestamp AS VARCHAR) ,1 ,17) || '30'
   -- 30〜59秒はhh:mm:00
   ELSE SUBSTRING(CAST((_timestamp + INTERVAL '30 SECOND') AS VARCHAR) ,1 ,17) || '00'
  END AS _timestamp_nsec
,SUM(_value) AS sum_value ,MIN(_value) AS min_value ,MAX(_value) AS max_value ,AVG(_value) AS avg_value
FROM TIMESUMTEST GROUP BY _timestamp_nsec ORDER BY _timestamp_nsec
   _timestamp_nsec   | sum_value | min_value | max_value |      avg_value
---------------------+-----------+-----------+-----------+---------------------
 2016-04-01 17:00:30 |      1551 |        28 |        65 | 51.7000000000000000
 2016-04-01 17:01:00 |      1677 |        39 |        77 | 55.9000000000000000
 2016-04-01 17:01:30 |      1785 |        44 |        74 | 59.5000000000000000
 2016-04-01 17:02:00 |      1720 |        34 |        86 | 57.3333333333333333
 2016-04-01 17:02:30 |      1779 |        38 |        77 | 59.3000000000000000
 2016-04-01 17:03:00 |      1838 |        31 |        85 | 61.2666666666666667
 2016-04-01 17:03:30 |      1890 |        41 |        93 | 63.0000000000000000
 2016-04-01 17:04:00 |      1810 |        39 |        94 | 60.3333333333333333
 2016-04-01 17:04:30 |      1698 |        35 |        78 | 60.6428571428571429
 2016-04-01 17:05:00 |      1894 |        46 |        89 | 63.1333333333333333
 2016-04-01 17:05:30 |        57 |        57 |        57 | 57.0000000000000000

その他

10秒単位、1分単位なら先頭からn文字取り出すだけで済みます。

/* 10秒単位 */
SELECT
 SUBSTRING(CAST(_timestamp AS VARCHAR) ,1 ,18) || '0' AS _timestamp_nsec
,SUM(_value) AS sum_value ,MIN(_value) AS min_value ,MAX(_value) AS max_value ,AVG(_value) AS avg_value
FROM TIMESUMTEST
GROUP BY _timestamp_nsec ORDER BY _timestamp_nsec

/* 60秒(1分)単位 */
SELECT
 SUBSTRING(CAST(_timestamp AS VARCHAR) ,1 ,16) AS _timestamp_nsec
,SUM(_value) AS sum_value ,MIN(_value) AS min_value ,MAX(_value) AS max_value ,AVG(_value) AS avg_value
FROM TIMESUMTEST
GROUP BY _timestamp_nsec ORDER BY _timestamp_nsec

Datadog Monitorで復旧通知を行わない方法

DatadogのMonitorでの通知設定で復旧(Recovery)通知を行わない方法です。

f:id:htnosm:20160121024220j:plain

template variables 内に通知先を設定する

f:id:htnosm:20160121024221p:plain

通知先を含めて {{#is_alert}}{{/is_alert}} もしくは {{^is_recovery}}{{/is_recovery}} 内に記載 します。

言われてみればなるほどなのですが、しばらくこの発想に至らず、復旧通知は必須なのかと誤解していました。
以下誤解していた理由(言い訳)です。

例文を見ただけではわからなかった

f:id:htnosm:20160121024223p:plain

初期表示状態の例文を見て、 {{#is_alert}}|{{#is_recovery}}を使って、異常時と復旧時の通知メッセージを変える物と認識しました。 (そのような使い方ももちろん可能です)

通知先指定時に末尾に設定される

f:id:htnosm:20160121024222p:plain

このような感じで(3)のアラート文面を書いた後に(4)の通知先を設定すると、アラート文面の末尾に通知先が追記されます。

f:id:htnosm:20160121024219p:plain

そのため、変数({{#is_alert}}{{/is_alert}}など)の中に通知先を入れられると考えませんでした。

尚、ドキュメント内にも通知先をtemplate variables内に設定する例はありませんでした。


■い頭は●くしないといけないと思いました。

AWS CloudWatch Logs S3へのエクスポートで少々ハマった事

CloudWatchに Export data to Amazon S3 という CloudWatch Logs で収集したログをS3へエクスポートする機能があります。 使用方法は公式ドキュメントにある通りですが、 実行した際に少々ハマった(面喰らった)ことを記載します。

公式ドキュメントはこちら。

目次

  1. S3 bucket prefix 末尾は "/" 不要
  2. 複数エクスポートタスクの作成不可

S3 bucket prefix 末尾は "/" 不要

Export data to Amazon S3 ダイアログ上でエクスポート先のS3バケットを指定しますが、Prefixの末尾に "/" を付けると無名の階層(フォルダ)が作られてしまいます。
致命的では無いですが、初見は表示のバグか何かかと思ってしまいました。そして少々不便です。

実例

S3 bucket prefix 末尾に"/"を付けて実行

f:id:htnosm:20160107194533p:plain

無名フォルダが作られる

f:id:htnosm:20160107194536p:plain

[Name]列は空ですが、クリックすると配下の階層へは移動できます。

無名フォルダだとパンくずリストから戻ることはできない

f:id:htnosm:20160107194535p:plain

リンクがないのでクリックして戻ることはできません。

複数エクスポートタスクの作成不可

エクスポートタスクが実行(Running)中の場合、新しいエクスポートタスクが作成できません。
実行中はマネジメントコンソール上は "Exporting * items" と表示されています。

f:id:htnosm:20160107194534p:plain

CLIでも実行(create-export-task)してみましたがエラーとなりました。

A client error (LimitExceededException) occurred when calling the CreateExportTask operation: Resource limit exceeded.

頻繁に使う機能では無いのでそれ程問題にはならないのか、 今の所ドキュメント記載(注意書き)は無いようです。

RabbitMQ HTTP APIドキュメントのバージョン別参照方法

兎さんのページで迷ったのでメモ。

f:id:htnosm:20151124001333j:plain

バージョン別HTTP APIドキュメント

頻繁に更新されるので検索エンジンの検索結果は当てになりません。 (古いバージョンのページに行き着く事が多々あります。)

兎にも角にも公式サイトのDocsページヘ行きます。

RabbitMQ - Messaging that just works

f:id:htnosm:20151124001334p:plain

a) 最新版を参照する

現在の最新版は3.5.6です。

  • PluginsのManagementから…

f:id:htnosm:20151124001335p:plain

  • Getting startedのlatest HTTP API documentation here

f:id:htnosm:20151124001336p:plain

最新版(v3.5.6)のドキュメントに辿り着きます。

f:id:htnosm:20151124001337p:plain

b) バージョン指定で辿る

旧バージョンを参照したいときは、

  • Documentation for previous stable releasesから…

f:id:htnosm:20151124001338p:plain

  • バージョンを選択(今回は3.4.x)

f:id:htnosm:20151124001339p:plain

  • PluginsのManagementから…

f:id:htnosm:20151124001340p:plain

よく見るとバックグラウンドイメージにもpreviousの文字があります。

  • Getting startedのlatest HTTP API documentation here

f:id:htnosm:20151124001341p:plain

選択したバージョン(v3.4.4)のドキュメントに辿り着きます。

f:id:htnosm:20151124001342p:plain

RabbitMQ エクスポート/インポート

RabbitMQでクラスタ化せずに vhost,exchange等を移行できます。

f:id:htnosm:20151124004337j:plain

RabbitMQのAPIを介して行えます。
尚、administrator権限が必要になるので、接続ユーザに予め権限付与しておきます。

# ユーザ追加
rabbitmqctl add_user "ユーザ名" "パスワード"
# administrator付与
rabbitmqctl set_user_tags "ユーザ名" administrator

エクスポート

  • definitions.jsonに出力
_src_user=
_src_pass=
_src_ip=
_src_port=

# Export
curl -s -S -u ${_src_user}:${_src_pass} \
  http://${_src_ip}:${_src_port}/api/definitions > definitions.json

インポート

  • definitions.jsonから入力
_dst_user=
_dst_pass=
_dst_ip=
_dst_port=

# Import
curl -s -S -X POST -u ${_dst_user}:${_dst_pass} \
  -H "content-type:application/json" -d "@definitions.json" \
  http://${_dst_ip}:${_dst_port}/api/definitions

簡易バックアップにも使えそうです。