[aws-cli] EC2スケールアップした時にELB配下だったら、一度外して再度参加させるやつ

スケールアップするためにインスタンス停止したら、ELBに再度参加させないと、いつまでも Out of Service のことってあるよね…

#!/bin/sh
INSTANCE_ID="${1}"
INSTANCE_TYPE="${2}"
# 指定されたインスタンスタイプが現在のものと同じだったら何もしない
CURRENT_INSTANCE_TYPE=`aws ec2 describe-instances –instance-ids ${INSTANCE_ID} | jq -r '.Reservations[].Instances[].InstanceType'`
if [ "${CURRENT_INSTANCE_TYPE}" = "${INSTANCE_TYPE}" ]; then
echo "current instance type : ${CURRENT_INSTANCE_TYPE}"
exit 0
fi
# ELB 配下かどうか確認
ELB_NAME=''
ELBS=`aws elb describe-load-balancers | jq -r ".LoadBalancerDescriptions[].LoadBalancerName"`
for ELB in ${ELBS}; do
ELB_INSTANCE_IDS=`aws elb describe-instance-health –load-balancer-name ${ELB} | jq -r ".InstanceStates[].InstanceId"`
for ELB_INSTANCE_ID in ${ELB_INSTANCE_IDS}; do
if [ "${ELB_INSTANCE_ID}" = "${INSTANCE_ID}" ]; then
ELB_NAME="${ELB}"
break
fi
done
ELB_INSTANCE_IDS=''
if [ "${ELB_NAME}" != "" ]; then
break;
fi
done
# ELB 配下だったら取り外す
if [ "${ELB_NAME}" != "" ]; then
echo " Remove ELB: ${INSTANCE_ID} from ${ELB_NAME}"
aws elb deregister-instances-from-load-balancer –load-balancer-name=${ELB_NAME} –instances=${INSTANCE_ID}
fi
# インスタンス停止して、stopped になるまで待つ
while :
do
EC2_STATE=`aws ec2 describe-instances –instance-ids ${INSTANCE_ID} | jq -r '.Reservations[].Instances[].State | .Name'`
echo "${INSTANCE_ID} : ${EC2_STATE}"
if [ "${EC2_STATE}" = "running" ]; then
aws ec2 stop-instances –instance-ids ${INSTANCE_ID}
fi
if [ "${EC2_STATE}" = "stopped" ]; then
break
fi
sleep 10
done
# インスタンスタイプを変更する
aws ec2 modify-instance-attribute –instance-id ${INSTANCE_ID} –instance-type ${INSTANCE_TYPE}
# インスタンス開始して、running になるまで待つ
aws ec2 start-instances –instance-ids ${INSTANCE_ID}
while :
do
EC2_STATE=`aws ec2 describe-instances –instance-ids ${INSTANCE_ID} | jq -r '.Reservations[].Instances[].State | .Name'`
echo "${INSTANCE_ID} : ${EC2_STATE}"
if [ "${EC2_STATE}" = "running" ]; then
break
fi
sleep 10
done
# ELB に参加させる
if [ "${ELB_NAME}" != "" ]; then
echo " Add ELB: ${INSTANCE_ID} to ${ELB_NAME}"
aws elb register-instances-with-load-balancer –load-balancer-name=${ELB_NAME} –instances=${INSTANCE_ID}
fi

view raw
gistfile1.sh
hosted with ❤ by GitHub

参考URL: http://dev.classmethod.jp/cloud/aws/elb-re-register/

[wp-cli] wp-cli と jq で wp-cron に登録されているイベントをすべて実行する

#!/bin/sh
wp_root="/path/to/wordpress"
wp="wp –path=${wp_root}"
hooks=`${wp} cron event list –format=json | jq -r '.[] | select(.next_run_relative == "now") | .hook'`
for hook in ${hooks} ; do
echo "***** run event ${hook} *****"
${wp} cron event run ${hook}
echo ""
done

view raw
wp_cron_event_run.sh
hosted with ❤ by GitHub

jq 便利すなぁ

[AWS] AWSのCloudWatchで取得できるBillingの情報を毎日Slackに通知させて費用を常に把握する

#!/bin/sh
# 昨日の日付
yesterday=`date -d '1 days ago' +%Y-%m-%d`
# 一日分の Maximum 値を使って
period='86400'
statistics='Maximum'
# CloudWatchからBillingのデータを持ってくる
billing=`aws –region us-east-1 cloudwatch get-metric-statistics \
–namespace 'AWS/Billing' \
–dimensions "Name=Currency,Value=USD" \
–metric-name EstimatedCharges \
–start-time "${yesterday} 00:00:00" \
–end-time "${yesterday} 23:59:59" \
–period ${period} –statistics "${statistics}" \
| jq ".Datapoints[].${statistics}"`
strings="${yesterday}までのAWSの利用費(月毎)です。 EstimatedCharges : \$${billing}"
# DevOpsManに伝える
curl -s https://slack.com/api/chat.postMessage -X POST \
-d "channel=#CHANNEL" \
-d "text=${strings}" \
-d "username=USER" \
-d "icon_emoji=:ICON:" \
-d "token=xoxp-0000000000-0000000000-0000000000-000000"

view raw
gistfile1.sh
hosted with ❤ by GitHub

参考: AWSのCloudWatchで取得できるBillingの情報を毎日Slackに通知させて費用を常に把握する – さよならインターネット

参考URLだと ruby で処理してるけど、aws-cli, jq と curl 使ってるだけだから、ruby 使わなくても sh だけでいいんでないかなーと思った

Re: WordPressで自動生成されるrobots.txt

WordPressの場合、ダッシュボードの「プライバシー設定」にあわせて自動でrobots.txtを生成してくれます(自分で robots.txt を設置した場合はそちらが優先されます)。

細かな設定を行いたい場合は自分で robots.txt を作成した方が早いかも知れませんが、当該部分にフィルターが用意されているので、プラグインやテーマでカスタマイズすることも可能です。

WordPressで自動生成されるrobots.txt | Gatespace's Blog

惜しい、Function Reference/do robots にもあるようにdo_robotstxt アクションフックが直前で呼ばれるので、そのアクションフックで robots_txt フィルターフックを登録したほうが確実。

<?php
add_action('do_robotstxt', function(){
  add_filter('robots_txt', function($output) {
    $public = get_option( 'blog_public' );
    if ( '0' != $public ) { // open
      $output .= "Disallow: /members/n";
    }
    return $output;
  }
}

[PHP] docomo 雑談対話 API

docomo が提供してくれている 雑談対話API をさくっと php で使う方法。

<?php
/*****
* https://dev.smt.docomo.ne.jp/?p=docs.api.page&api_docs_id=5
*****/
function webnist($text) {
$context_file = dirname(__FILE__).'/.docomoapi.context';
$api_key = 'your API key here';
$api_url = sprintf('https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=%s&#39;, $api_key);
$req_body = array('utt' => $text);
if ( file_exists($context_file) ) {
$req_body['context'] = file_get_contents($context_file);
}
$headers = array(
'Content-Type: application/json; charset=UTF-8',
);
$options = array(
'http'=>array(
'method' => 'POST',
'header' => implode( "\r\n", $headers ),
'content' => json_encode($req_body),
)
);
$stream = stream_context_create( $options );
$res = json_decode(file_get_contents($api_url, false, $stream));
if (isset($res->context)) {
file_put_contents($context_file, $res->context);
}
return isset($res->utt) ? $res->utt : '';
}

curl で試したいときは、こんな感じ

curl -s --insecure \
 -H "Content-Type: application/json; charset=UTF-8" \
 https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=XXXXXX \
 -d "{\"utt\":\"アイス食べたい\"}"

view raw
gistfile1.md
hosted with ❤ by GitHub

まともに使いたければ https://github.com/fetus-hina/docomo-dialogue とかのライブラリ使うといいと思うよ。

[AWS] Lambda から Lambda を呼ぶ

ようやく AWS Lambda が把握できてきた。
小さい機能単位で Lambda ファンクション作って、それを呼ぶ感じで作っていくとやりやすい。

イベント発生して呼び出される Lambda ファンクション

イベントの情報をもとになんかする Lambda ファンクション

結果を SNS なり、Slack なりに投げる Lambda ファンクション

みたいに Lambda ファンクションから Lambda ファンクションを呼び出して作業させると具合がいい
Lambda から Lambda を呼ぶには

console.log('Loading event');
var aws = require('aws-sdk');

exports.handler = function(event, context) {
    // なんか処理

    var lambda = new aws.Lambda({apiVersion: '2014-11-11'});
    var params = {
        FunctionName: "lambda-function-name",
        InvokeArgs: JSON.stringify({
            "key_1": 'var_1',
            "key_2": 'var_2',
            "key_3": 'var_3'
            }, null, ' ')
        };
    lambda.invokeAsync(params, function(err, data){
        if(err) context.done('error', err.stack);
        else context.done(null, '');
}

Lambda から SNS を呼ぶには

var sns = new aws.SNS({region: 'リージョン'});
var params = {
    TopicArn: 'トピック arn',
    Subject: 'サブジェクト',
    Message: 'メッセージ'
  };
  sns.publish(params, function(err, data) {
    if(err) context.done('error', err.stack);
    else context.done(null, '');
  })

[AWS] Lambda でS3 にファイルをアップロードしたら typetalk チャットに通知するやつ

参考: AWS Lambda でS3 にファイルをアップロードしたらSlackチャットに通知するやつ

元記事では Slack だったけど、typetalk も業務でお世話になってるので、Typetalk 対応もしてみた。
Typetalk API

const TYPETALK_TOKEN = "....";

var req = require('request');

exports.handler = function(event, context) {
    var filename = event.Records[0].s3.object.key;
    typetalk(TYPETALK_TOKEN, "your typetalk toppick id", "Put: "+filename);
};

function typetalk(token, topic_id, message) {
    req.post('https://typetalk.in/api/v1/topics/'+topic_id+'?typetalkToken='+token)
        .form({
            message: message
        })
        .on('response', function (response) {
          response.on('data', function(data) {
            context.done(null, data);
          });
        })
        .on('error', function (err) {
            cotext.done(err, 'Failed post the chat');
        });
}

https://github.com/wokamoto/aws-lambda-samples/tree/master/s3slack

[Nginx] CloudFront を前面に置いたときに css が gzip 転送されないときへの対処

Nginx をオリジンサーバにして CloudFront を設置したときにテキストファイルが gzip 圧縮転送されないときは nginx.conf に以下を追加する。

gzip_proxied any;
gzip_http_version 1.0;

参考: Serving Compressed Files – Amazon CloudFront

網元 AMI で対応するなら、以下の手順で

$ sudo sh -c 'echo "gzip_proxied any;" > /etc/nginx/conf.d/gzip_proxied.conf'
$ sudo service nginx reload

[Nginx] Nginx で S3 をリバースプロキシする

location ~* ^/(get_s3)/(.*) {
set $s3_bucket 'your_s3_bucket_name.s3.amazonaws.com';
set $url_full "/$1/$2";
proxy_http_version 1.1;
proxy_set_header Host $s3_bucket;
proxy_set_header Authorization '';
proxy_hide_header x-amz-id-2;
proxy_hide_header x-amz-request-id;
proxy_hide_header Set-Cookie;
proxy_ignore_headers "Set-Cookie";
proxy_buffering off;
proxy_intercept_errors on;
resolver 172.16.0.23 valid=300s;
resolver_timeout 10s;
proxy_pass http://$s3_bucket/$url_full;
}

view raw
gistfile1.nginxconf
hosted with ❤ by GitHub

参考:
http://davidburgosonline.com/dev-ops/2014/configure-nginx-amazon-s3/
https://coderwall.com/p/rlguog/nginx-as-proxy-for-amazon-s3-public-private-files

可用性は落ちちゃうけど、例えば S3 上のテキストファイルを gzip 圧縮転送したいとか、https + spdy で配信したいとかに使おう