【LINE Notify】シェルスクリプトでWEBスクレイピングしてみた【bash】

よくチェックするサイトに新着記事が投降されたら、LINE NotifyのAPIを叩いて通知するコードを書いてみました。

#!/bin/bash

# LINEのTOKENを定義
TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# WEBページの情報を取得
MSG=`curl https://www.megamouth.info/archive | grep "<a class=\"entry-title-link\"" | sed -e 's/<[^>]*>//g' | nl`
# 作業ディレクトリの定義
OPE_DIR=/opt/SCRAPING/megamouth
# 実行時のWEBページ情報を記録するファイルを定義
INFO_FILE=$OPE_DIR/info.txt
# 前回実行時のWEBページ情報を記録するファイルを定義
PRE_INFO_FILE=$OPE_DIR/pre_info.txt

if [ ! -e $OPE_DIR ]; then
        # ディレクトリの作成
        mkdir -p $OPE_DIR
fi

# 前回実行時の記録ファイルが無ければ作成し通知
if [ ! -e $PRE_INFO_FILE ]; then
        curl https://www.megamouth.info/archive | grep "<a class=\"entry-title-link\"" | sed -e 's/<[^>]*>//g' | nl > $PRE_INFO_FILE
        curl -X POST -H "Authorization: Bearer ${TOKEN}" -F "message=${MSG}" https://notify-api.line.me/api/notify
        exit 0
fi

# 今回取得した情報を変数に代入
curl https://www.megamouth.info/archive | grep "<a class=\"entry-title-link\"" | sed -e 's/<[^>]*>//g' | nl > $INFO_FILE

# 前回と今回取得した情報を比較
diff -s $INFO_FILE $PRE_INFO_FILE

# DIFFの実行結果を変数に代入
DIFF_STATUS=$?

if [ ${DIFF_STATUS} -eq 1 ]; then
        # 前回取得した情報と今回取得した情報に差異があれば通知
        curl -X POST -H "Authorization: Bearer ${TOKEN}" -F "message=${MSG}" https://notify-api.line.me/api/notify
elif [ ${DIFF_STATUS} -eq 2 ]; then
        # diff実行時にエラーが発生すればエラーを通知
        curl -X POST -H "Authorization: Bearer ${TOKEN}" -F "message=error" https://notify-api.line.me/api/notify
fi

# 情報ファイルを更新
cp -fp $INFO_FILE $PRE_INFO_FILE

なんだかもっといろいろと使えそうですね。
アラート通知とか。。
↓皆さんもぜひ
LINE Notify

【チラ裏】SSL(TLS)証明書関連【openssl】

SSL(というかTLS)証明書関連ですね。
いつもどおりのチラ裏です。

証明書の整合性確認

# 秘密鍵
openssl rsa -noout -text -in test.com.key
# 証明書
openssl x509 -noout -text -in test.com.crt
# 中間証明書
openssl x509 -noout -text -in test.com.ca

・秘密鍵、証明書の「Modules」の値が同じであること
・証明書のIssuer:CNと中間証明書のSubject:CNが同じであること

秘密鍵、CSR作成

# 秘密鍵作成
openssl genrsa -aes256 2048 > test.com.key

# CSR作成
openssl req -new -key test.com.key -out test.com.csr
=========================================================
Country Name:
ISOによる2文字の国名の符号
→JP

State or Province Name:
都道府県名
→Osaka

Locality Name:
市区町村名
→Osaka

Organization Name:
組織名
→test,Co.,Ltd.

Organizational Unit Name:
部署名
→test

Common Name:
→test.com

その他便利なopenssl

# CSRの内容確認
openssl req -noout -text -in test.com.csr

# Keyファイルの確認
openssl rsa -noout -check -in test.com.key
RSA key ok

# CSRとKeyファイルの比較
openssl rsa -in test.com.key -text
openssl req -in test.com.csr -text
⇒mosulusの値を比較し、差異が無いことを確認

# 秘密鍵のパスフレーズを解除
openssl rsa -in test.com.key -out test.com.key
openssl rsa -in test.com -text

【Nginx】Nginx での リバースproxy 設定

Nginx のリバースproxy 設定に関して纏めておきます。

例1

server {
    listen       443 ssl;
    server_name  test.com www.test.com;

    client_max_body_size 12m;
    proxy_set_header Host $http_host;

    ssl_certificate /etc/certs/test.com/current/test.com.pem;
    ssl_certificate_key /etc/certs/test.com/current/test.com.key;

    location / {
        proxy_pass http://localhost:8008;
        proxy_set_header Host              $host;
        proxy_set_header X-Forwarded-HTTPS on;
        proxy_set_header X-Forwarded-SSL   on;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Nginx の443で受けてlocalの 8008 に渡す感じですね。
Nginx で ssl終端させる感じですね。

例2

server {
    listen       443 ssl;
    server_name  www.test.com;
    client_max_body_size 12m;

    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-HTTPS on;
    proxy_set_header X-Forwarded-SSL   on;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_buffer_size 32k;
    proxy_buffers 50 32k;
    proxy_busy_buffers_size 32k;

    ssl_certificate /etc/certs/test.com/current/www.test.com.pem;
    ssl_certificate_key /etc/certs/test.com/current/www.test.com.key;

    location / {
        proxy_pass https://192.168.33.10:443;
    }

include /etc/nginx/proxy_virtual/www.test.com/*.conf;

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

     location ~ (\/api)(\/.*)?{
        proxy_pass https://localhost:8008;
    }

/api でのアクセスであれば local の 8008 に proxy する設定ですね。
それ以外は https://192.168.33.10:443 に proxy させます。
※ L7 での proxy ですね。

【チラ裏】ディスク拡張【growpart】

自分用のメモになります。

yum whatprovides growpart
yum install cloud-utils-growpart-0.29-5.el7.noarch
lsblk
growpart /dev/sdb 1
lsblk
df -h
xfs_growfs /dev/sdb1
lsblk
df -h

パーティション拡張( growpart ) ⇒ ファイルシステム拡張( xfs_growfs )ですね。
ext4 の場合は、resize2fs ですね。

※ 追記↓

【AWS】ダウンタイムなくルートパーティションを拡張してみる【ディスク拡張】

【Ansible】アクセス制限用のモジュールを作成する【シェルスクリプト】

Ansible の 標準モジュールに良さげなモジュールがなかったんで、んじゃいっそ作ってみようかと。

ディレクトリ構造

├── README.md
├── ansible.cfg
├── block.yml
├── group_vars
│   └── main.yml
├── hosts
├── library
│   └── block_ip.sh
└── roles
    └── block_ip
        ├── README.md
        ├── tasks
        │   └── main.yml
        └── vars
            └── main.yml

モジュール

root@DESKTOP-MOGIJIA:/opt/playbook/ip_block# cat library/block_ip.sh
#!/bin/sh
source `dirname $0`/args

if [ $state == "absent" ] ; then
        route del -host $target reject
        if [ $? -eq 0 ] ; then
                echo '{ "rc": 0, "changed": true }'
        else
                echo '{ "rc": 0 }'
        fi
elif [ $state == "present" ] ; then
        route add -host $target reject
        if [ $? -eq 0 ] ; then
                echo '{ "rc": 0, "changed": true }'
        else
                echo '{ "rc": 0 }'
        fi
else
        echo '{ "failed": true, "rc": 0 }'
fi

library ディレクトリ以下にモジュールを作成します。
それと、playbook の中で target (対象IPアドレス)、 state (状態)を定義できるようにしておきます。

Role

root@DESKTOP-MOGIJIA:/opt/playbook/ip_block# cat roles/block_ip/tasks/main.yml
---
# tasks file for block_ip
- name: block_ip
  block_ip:
    target: "{{ item }}"
    state: absent
  with_items:
    - "{{ block_target }}"

- name: accept_ip
  block_ip:
    target: "{{ item }}"
    state: absent
  with_items:
    - "{{ accept_target }}"

「state」が「present」⇒アクセスを制限
「state」が「absent」⇒アクセス制限を解除
としておきます。
root@DESKTOP-MOGIJIA:/opt/playbook/ip_block# cat group_vars/main.yml
---
   block_target:
     - 192.168.99.99
     - 192.168.99.98
     - 192.168.99.97
     - 192.168.99.96
     - 192.168.99.95
     - 192.168.99.94
     - 192.168.99.93
     - 192.168.99.00

   accept_target:
     - 127.0.0.1

playbook

root@DESKTOP-MOGIJIA:/opt/playbook/ip_block# cat block.yml
---
# Main Playbook
- name: apply master configuration to master nodes
  hosts: all
  vars_files:
   - ./group_vars/main.yml
  remote_user: vagrant
#  remote_user: centos
  become: yes
  roles:
    - block_ip

実行

root@DESKTOP-MOGIJIA:/opt/playbook/ip_block# ansible-playbook block.yml --ask-pass
SSH password:

PLAY [apply master configuration to master nodes] **********************************************************************

TASK [Gathering Facts] *************************************************************************************************
ok: [192.168.33.10]

TASK [block_ip : block_ip] *********************************************************************************************
changed: [192.168.33.10] => (item=192.168.99.99)
changed: [192.168.33.10] => (item=192.168.99.98)
changed: [192.168.33.10] => (item=192.168.99.97)
changed: [192.168.33.10] => (item=192.168.99.96)
changed: [192.168.33.10] => (item=192.168.99.95)
changed: [192.168.33.10] => (item=192.168.99.94)
changed: [192.168.33.10] => (item=192.168.99.93)
changed: [192.168.33.10] => (item=192.168.99.00)

TASK [block_ip : accept_ip] ********************************************************************************************
ok: [192.168.33.10] => (item=127.0.0.1)

PLAY RECAP *************************************************************************************************************
192.168.33.10              : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

結果

[root@ansible-dev ~]# ip route show
default via 10.0.2.2 dev eth0 proto dhcp metric 100
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15 metric 100
192.168.33.0/24 dev eth1 proto kernel scope link src 192.168.33.10 metric 101
unreachable 192.168.99.0 scope host
unreachable 192.168.99.93 scope host
unreachable 192.168.99.94 scope host
unreachable 192.168.99.95 scope host
unreachable 192.168.99.96 scope host
unreachable 192.168.99.97 scope host
unreachable 192.168.99.98 scope host
unreachable 192.168.99.99 scope host
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1

うん、大丈夫ですね。

【データ移行】/var を別の追加ディスクに移行【Tips】

こんにちは。
/var のディレクトリを別の追加ディスクに移行する手順を残しておきます。

[root@test-server /]# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
vda    253:0    0   30G  0 disk
mqvda1 253:1    0 29.3G  0 part /
vdb    253:16   0  100G  0 disk

/dev/vdb の領域に /var を移行してみます。

手順

・ファイルシステムの作成
/dev/vdb にパーティションを切ってからファイルシステムを作成します。

[root@test-server /]# fdisk /dev/vdb
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table
Building a new DOS disklabel with disk identifier 0xf4f00fe7.

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-209584127, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-209584127, default 209584127): +100G
Value out of range.
Last sector, +sectors or +size{K,M,G} (2048-209584127, default 209584127): ^[[A^[[D^[[B^[[B^C
[root@sr-stg-ftp01 /]# fdisk /dev/vdb
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table
Building a new DOS disklabel with disk identifier 0x71de9846.

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-209584127, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-209584127, default 209584127):
Using default value 209584127
Partition 1 of type Linux and of size 100 GiB is set

Command (m for help): p

Disk /dev/vdb: 107.3 GB, 107307073536 bytes, 209584128 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x71de9846

   Device Boot      Start         End      Blocks   Id  System
/dev/vdb1            2048   209584127   104791040   83  Linux

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

mkfs -t xfs /dev/vdb1

・シングルユーザモードへ
init 1

・追加ディスクをアタッチして/var を同期する
cd /
mkdir /new_var
mount -t xfs /dev/vdb1 /new_var
rsync -avzr /var/ /new_var/

・元の /var を別名保存し、/var へ vdb をマウント
umount /new_var
mv var var_old
mkdir var
mount -t xfs /dev/vdb1 /var

・fstab に追記
vi /etc/fstab
=================================
/dev/vdb1 /var xfs defaults 0 2

・マルチユーザモードへ
init 3

【Ansible】いい感じにデータを変数にいれる【シェルスクリプト】

スペース区切りだったり、カンマ区切りのデータをいい感じに Ansible の変数に入れたいことってありますよね。
そんな時によく使うスクリプトです。

シェルスクリプト

vi var_create.sh
===============================================
#!/bin/bash

while IFS=' ' read key val
do
  echo "     - { domain: '$val' ,owner: '$key' }"
done < $1

vi data.txt
============================
user1 aaa
user2 bbb
user3 ccc

実行

[root@keisuke-main tmp]# ./var_create.sh data.txt
     - { domain: 'aaa' ,owner: 'user1' }
     - { domain: 'bbb' ,owner: 'user2' }
     - { domain: 'ccc' ,owner: 'user3' }

【サーバ移設】踏み台サーバを経由してrsyncする方法【rsync】

こんにちは。
先日にサーバ移設案件に携わる機会があって、踏み台サーバを経由して、目的のサーバにデータを同期する必要がありました。
その際に先輩に教えてもらった方法をメモレベルで残しておこうと思います。

rsync 用ユーザ作成

useradd rsync
su rsync
cd ~
mkdir .ssh
chmod 700 .ssh

SSH 設定

vi /home/rsync/.ssh/config
===============================================
Host step-new
    HostName      111.111.111.111
    User          step-new-user
    IdentityFile  ~/.ssh/id_rsa_step-new.pem
Host step-old
    ProxyCommand  ssh -W %h:%p step-new
    HostName      222.222.222.222
    User          step-old-user
    IdentityFile  ~/.ssh/id_rsa_step-old.pem
Host target-server
    ProxyCommand  ssh -W %h:%p step-old
    HostName      333.333.333.333
    User          target-server-user
    IdentityFile  ~/.ssh/id_rsa_target.pem
===============================================

vi ~/.ssh/id_rsa_step-new.pem
vi ~/.ssh/id_rsa_step-old.pem
vi ~/.ssh/id_rsa_target.pem

chmod 600 ~/.ssh/id_rsa_step-new.pem
chmod 600 ~/.ssh/id_rsa_step-old.pem
chmod 600 ~/.ssh/id_rsa_target.pem

データ同期

mkdir -p /var/tmp/rsync_results/test1
nohup time rsync -avzrn --rsync-path="sudo rsync" target-server:/home/target-server-user/ /home/purpose/ 1>/var/tmp/rsync_results/test1/result_$(date +"%Y%m%d").log 2>/var/tmp/rsync_results/test1/error_$(date +"%Y%m%d").log &
nohup time rsync -avzr --rsync-path="sudo rsync" target-server:/home/target-server-user/ /home/purpose/ 1>/var/tmp/rsync_results/test1/result_$(date +"%Y%m%d").log 2>/var/tmp/rsync_results/test1/error_$(date +"%Y%m%d").log &

補足

・.ssh/ 以下に config ファイルを作成することで、踏み台サーバを経由して接続が出来る。
・秘密鍵は事前に配置しておく必要がある。

【tips】コメントアウトを省いて設定ファイルを確認する方法

お疲れ様です。
最近サーバの構築チームに移動になりました。
表題の通りです。

コメントアウトを省いて設定ファイルを確認する

grep -v -e '^\s*#' -e '^\s*$' 【設定ファイル】

例題

↓こんな感じです。

[root@ansible-dev etc]# grep -v -e '^\s*#' -e '^\s*$' /etc/ansible/ansible.cfg
[defaults]
roles_path    = /etc/ansible/roles:/usr/share/ansible/roles
[inventory]
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[accelerate]
[selinux]
[colors]
[diff]