Alexa スキルの応答で、
this.emit(':tell', "メッセージ");
のように、tellを使うと会話が終わり、改めてスキルを起動する必要がある。
this.emit(':ask', "メッセージ");
askを使うことで再度インテントを受け付けられた
Web、スマホアプリの開発、その他個人的なこと
Alexa スキルの応答で、
this.emit(':tell', "メッセージ");
のように、tellを使うと会話が終わり、改めてスキルを起動する必要がある。
this.emit(':ask', "メッセージ");
askを使うことで再度インテントを受け付けられた
Alexaスキルから実行するLambda 内で外部APIを利用したい。
APIの呼び出しを非同期で行ったところ、うまくいかなかった、、、
var options = {
uri: "https://xxxxxxx",
headers: {
"Content-type": "application/json",
},
json: {
"data1": "xxxx",
"data2": "yyyy"
}
};
request.post(options, function(error, response, body){
// this.emit(':tell', "外部API呼び出し"); // ← ここでemitを実行するとAPIコールするが、Alexaへの応答が空になる
});
// this.emit(':tell', "外部API呼び出し"); // ← ここでemitを実行するとAPIコールされず、Alexaへの応答は正常にされる
本来あるべき姿ではないと思うが、APIコールを同期的に行うことで一旦解決。
npm install sync-request
呼び出しはこんな感じ
var response = request(
'POST',
"https://xxxxxx",
{
json: {
"data1": "xxxxx",
"data2": "yyyy"
}
}
);
this.emit(':tell', "外部API呼び出し");
一応GETの場合はこんな感じ
var response = request(
'GET',
"https://xxxxxxx"
);
var data = JSON.parse(response.getBody('utf8'));
this.emit(':tell', "データ1は" + data.data1 + "です");
Lambda で開発していてコードをアップロードするのに毎回Webコンソールからアップロードするのは大変なのでシェルを組みます。
zipに圧縮して、S3にアップ、それをLambdaに紐付ける流れです。
実際のシェルはこんな感じです。
#!/bin/sh
zip -r app.zip index.js node_modules
aws s3 cp ./app.zip s3://{バケット名}/app.zip --profile={プロファイル}
aws lambda update-function-code --function-name {Lambdaファンクション名} --s3-bucket {バケット名} --s3-key app.zip --publish --profile={プロファイル}
SpringBootで作成したWebアプリケーションをElasticBeanstalkで運用していてAutoScalingなどでEC2が削除されると、EC2上に保存されているログファイルも当然削除されてしまう。
削除される前にログファイルをどこかに保存したいと思うのですが、その一つの方法としてCloudWatchに転送することにする。
ElasticBeanstalkにはCloudWatchにログファイルを連携する機能がありますが、今回はアプリケーション独自のログを連携したいのでこの機能(CloudWatch Logs へのインスタンスログのストリーミング)は使いません。
アプリケーションから出力した独自ログとapacheのログを転送することにします。
CloudWatchへの転送にはawslogsを使用します。
awslogsのインストールなどEC2への操作などはデプロイするWebアプリケーション内に設定ファイルとして追加します。
具体的には、アプリケーションの src/main/webapp/.ebextensions 以下に配置します。
.ebextensions 以下にconfigファイルを配置しますが、awslogsを使う場合は以下のような内容です。
packages:
yum:
awslogs: []
container_commands:
1-cp-awscli_conf:
command: cp -rf .ebextensions/awscli.conf /etc/awslogs/awscli.conf
2-cp-awslogs_conf:
command: cp -rf .ebextensions/awslogs.conf /etc/awslogs/awslogs.conf
3-chkconfig-awslogs:
command: /sbin/chkconfig awslogs on
4-restert-awslogs:
command: /sbin/service awslogs status; if [ $? -eq 0 ]; then /sbin/service awslogs restart; else /sbin/service awslogs start ; fi;
awslogsの設定ファイルも予め用意しておいて、そのファイルコピーします。
最終的なファイル構成はこんな感じです。
awscli.conf、awslogs.conf の内容も参考までに。
[plugins]
cwlogs = cwlogs
[default]
region = ap-northeast-1
[general]
state_file = /var/lib/awslogs/agent-state
[/var/log/httpd/access_log]
log_group_name = sample_app
log_stream_name = {instance_id}_httpd
file = /var/log/httpd/access_log
datetime_format = %d/%b/%Y:%H:%M:%S
initial_position = start_of_file
buffer_duration = 5000
[/var/log/tomcat8/sample_app.log]
log_group_name = sample_app
log_stream_name = {instance_id}_app
file = /var/log/tomcat8/sample_app.log
datetime_format = %Y-%m-%d %H:%M:%S.
initial_position = start_of_file
buffer_duration = 5000
もちろんログのファイル名や、日付けフォーマットなどを合わせる必要があります。
apache設定にリダイレクト設定を追加するので設定ファイルを開き、
sudo vi /opt/bitnami/apache2/conf/bitnami/bitnami.conf
以下のリダイレクト設定を追加。
<VirtualHost _default_:80>
DocumentRoot "/opt/bitnami/apache2/htdocs"
# Redirect
RewriteEngine On
RewriteRule ^/(.*) https://%{HTTP_HOST}/$1 [R=301,L]
追加後にapacheの再起動。
sudo /opt/bitnami/ctlscript.sh restart apache
以下のように条件をつけても良かったが、VirtualHostで80ポートにきたら無条件でリダイレクトにした。
RewriteCond %{HTTPS} off
EBSのスナップショットを作成するバッチを作り、cronで動かす。
#!/bin/sh
SHELLDIR=`dirname ${0}`
SHELLDIR=`cd ${SHELLDIR}; pwd`
SHELLNAME=`basename $0`
LOG_DIR="/root/logs"
LOG_SAVE_PERIOD=14
LOG_FILE="${LOG_DIR}/${SHELLNAME}.log"
AZ=`curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone`
LN=`echo $((${#AZ} - 1))`
REGION=`echo ${AZ} | cut -c 1-${LN}`
SNAPSHOTS_PERIOD=2
AWS="/usr/bin/aws --region ${REGION}"
INSTANCE_ID=`curl -s http://169.254.169.254/latest/meta-data/instance-id`
CREATED_BY="Created by CreateSnapshotShell"
rotate_log() {
(( cnt=${LOG_SAVE_PERIOD} ))
while (( cnt > 0 ))
do
logfile1=${LOG_FILE}.$cnt
(( cnt=cnt-1 ))
logfile2=${LOG_FILE}.$cnt
if [ -f $logfile2 ]; then
mv $logfile2 $logfile1
fi
done
if [ -f $LOG_FILE ]; then
mv ${LOG_FILE} ${LOG_FILE}.1
fi
touch $LOG_FILE
}
print_msg() {
echo "`date '+%Y/%m/%d %H:%M:%S'` $1" | tee -a ${LOG_FILE}
}
set_vol_id() {
VOL_ID=`${AWS} ec2 describe-instances --instance-ids ${INSTANCE_ID} --output text | grep EBS | awk '{print $5}'`
}
create_snapshot() {
print_msg "Create snapshot Start"
if [ -z ${VOL_ID} ] ; then
echo ${VOL_ID}
print_msg "ERR:ec2-describe-instances"
logger -f ${LOG_FILE}
exit 1
fi
print_msg "ec2-describe-instances Success : ${VOL_ID}"
${AWS} ec2 create-snapshot --volume-id ${VOL_ID} --description "${CREATED_BY}(${INSTANCE_ID}) from ${VOL_ID}" >> ${LOG_FILE} 2>&1
if [ $? != 0 ] ; then
print_msg "ERR:${SHELLDIR}/${SHELLNAME} ec2-create-snapshot"
logger -f ${LOG_FILE}
exit 1
fi
print_msg "Create snapshot End"
}
delete_old_snapshot() {
print_msg "Delete old snapshot Start"
SNAPSHOTS=`${AWS} ec2 describe-snapshots --output text | grep ${VOL_ID} | grep "${CREATED_BY}" | wc -l`
while [ ${SNAPSHOTS} -gt ${SNAPSHOTS_PERIOD} ]
do
${AWS} ec2 delete-snapshot --snapshot-id `${AWS} ec2 describe-snapshots --output text | grep ${VOL_ID} | grep "${CREATED_BY}" | sort -k11 | awk 'NR==1 {print $10}'` >> ${LOG_FILE} 2>&1
if [ $? != 0 ] ; then
print_msg "ERR:${SHELLDIR}/${SHELLNAME} ec2-delete-snapshot"
logger -f ${LOG_FILE}
exit 1
fi
SNAPSHOTS=`${AWS} ec2 describe-snapshots | grep ${VOL_ID} | grep "${CREATED_BY}" | wc -l`
done
print_msg "Delete old snapshot End"
}
rotate_log
print_msg "INF:$SHELLDIR/${SHELLNAME} START"
set_vol_id
create_snapshot
delete_old_snapshot
print_msg "INF:$SHELLDIR/${SHELLNAME} END"
exit 0
を、スナップショットを取得したいEC2に保存してcronを設定する。
# backup EBS
0 17 * * * /root/tools/createSnapshot.sh
sudo /opt/bitnami/apps/wordpress/bnconfig --disable_banner 1
ユーザーは”user”固定ですがパスワードが不明なので、SSHで接続して、
cat bitnami_application_password
https://{ドメイン名}/wp-login.php にアクセスしてログインする。
セキュリティ上、デフォルトの”wp-login.php”を変更する。
今回は“SiteGuard WP Plugin” “WPS Hide Login”を使用しました。
Lightsailのロードバランサーを使用すれば、AWSで生成するSSLを利用できるが予算の関係で無料のSSL、Let’s Encryptを使用する。
キーペアーを使用してローカルからSSHクライアントで接続も可能ですが、Webコンソールからも接続できます。
$ sudo apt-get install letsencrypt python-letsencrypt-apache
$ sudo letsencrypt certonly --webroot -w /opt/bitnami/apps/wordpress/htdocs/ -d {ドメイン名}
こんな画面でメールアドレスの確認と規約への同意を求められます。
$ sudo cp /etc/letsencrypt/live/{ドメイン名}/fullchain.pem /opt/bitnami/apache2/conf/server.crt
$ sudo cp /etc/letsencrypt/live/{ドメイン名}/privkey.pem /opt/bitnami/apache2/conf/server.key
$ sudo /opt/bitnami/ctlscript.sh restart apache