カメニッキ

カメとインコと釣りの人です

コピペでssl_ciphers(暗号化スイート)の指定をやってたけど、もうちょっと調べてみた

tapira.hatenablog.com

SSL Server Testで A+ 判定を得るために、Generate Mozilla Security Recommended Web Server Configuration Files で生成した設定を一部利用しています。 その中でも特に目につくのが↓のなっがいやつでした。

    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';

そもそも暗号化スイートとは?

鍵交換方式 & 鍵認証のアルゴリズム & 共通鍵暗号アルゴリズム & 利用するハッシュ関数 を組み合わせたものを、 暗号化スイート と呼ぶそうです。

ssl_ciphersで先頭にきている一番のおすすめ(?) ECDHE-RSA-AES128-GCM-SHA256 を例にとってみます。

  1. 鍵交換方式(Kx)に ECDHE(楕円曲線ディフィー・ヘルマン鍵共有 - Wikipedia - Elliptic curve Diffie–Hellman key exchange)を使う
    Kxは「安全でない経路で結ばれたサーバとクライアント間で共通鍵を安全に交換する」という目的を達するための仕組み。 公開鍵暗号の鍵交換を担う

  2. サーバ認証のアルゴリズム(Au)にRSA 実際に通信する相手が、証明書の持ち主か認証するための仕組み。 公開鍵暗号の署名を担う

  3. 暗号化の方法(Enc)に AES&GCM
    共通鍵を使用して暗号化通信する際の方式。 共通鍵を交換し終わったあと実際に情報をやり取りする際の暗号化・復号化を担う

  4. ハッシュアルゴリズム(Mac)に SHA256

で、いいのかな。KxとAuの役割の違いがよくわからんくなった。

結論

最新の 鍵交換方式 & 鍵認証のアルゴリズム & 共通鍵暗号アルゴリズム & 利用するハッシュ関数 を全部追っかけとかないといこうとすると辛いなーと思った。
何も考えずにコピペしない、という前提のもと Generate Mozilla Security Recommended Web Server Configuration Files などを参考に、内容を理解し、自身の環境に適用できるか検討したうえで選択する、というのが現実的なところか…

ちなみに

ssl_ciphers で完璧なものを指定しておけば安心!というわけではない(最近おしえてもらった)

  • ssl_prefer_server_ciphers on; でサーバ側の暗号化スイート設定を優先するようにしておかないと、クライアント側の設定が利用されて辛い
  • ssl_session_tickets off; デフォは有効なので、使わないのであれば明示的に off にする。(クラスタ構成にする場合は、複数台のnginxでsession cacheを共有するため有効にし、定期的にkeyの更新を行わせる必要がある。nginx.conf ssl_session_ticket_key /etc/nginx/ticket.key; とファイルを明示し、cronなどで openssl rand 48 > /etc/nginx/tickets.key で定期更新し、各nginxで同じものを使う。
  • ssl_session_timeout 5m; 有効期限が短ければ短いほど、安全なはず。サーバ負荷と相談しつつ設定
  • nginx外のそもそものサーバ設定。ミドルウェアの設定を頑張ってもfirewallが全空きでした!じゃ辛い

とても良い記事 qiita.com

tech.mercari.com

hb.matsumoto-r.jp

Let's Encryptを使用したkame.photosのSSL Server Test結果をA+にした

https://kame.photos/

f:id:tapira:20160131225443p:plain

参考

http {
    〜略〜
    # HTTP Strict Transport Security の指定。サブドメインにも適用
    add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains;';
    〜略〜
    server {
        listen  443 ssl http2;
        # プロトコルはTLS1.2に限定
        ssl_protocols TLSv1.2;
        # TLSセッションキャッシュ有効期限
        ssl_session_timeout 5m;
        # TLSセッションキャッシュを全ワーカプロセスで共有。サイズは50MB
        ssl_session_cache shared:SSL:50m;
        # DH鍵交換のパラメータファイルの指定「openssl dhparam 2048 -out dhparam.pem」で生成
        ssl_dhparam /etc/nginx/dhparam.pem;
        # 暗号化スイート指定(MozillaConfigGenerator参照)
        ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';
        # サーバサイドの暗号化スイート指定を優先
        ssl_prefer_server_ciphers on;
        # TLSセッションチケットはOFF - TLSセッションキャッシュはsession resumptionを使う
        ssl_session_tickets off;

        # OCSP Staplingを有効化にする
        ssl_stapling on;
        ssl_stapling_verify on;
        # 認証局の証明書
        ssl_trusted_certificate /etc/letsencrypt/live/kame.photos/ce-cert;
        
        ssl_certificate      /etc/letsencrypt/live/kame.photos/fullchain.pem;
        ssl_certificate_key  /etc/letsencrypt/live/kame.photos/privkey.pem;
    〜略〜

いろいろと気にするところがあるのだな〜とおもた

cclogconv(IPアドレスから国名を取得するツール)を使ってみた

github.com

???

[PMAC226S ~/src/github.com/rhykw/cclogconv]$ echo "111.169.213.70" | cclogconv --data ./GeoLite2-Country.mmdb
JP 111.169.213.70

とりあえずtmp直下にDBはおくように設定してビルド

[PMAC226S ~/src/github.com/rhykw/cclogconv]$ git diff
diff --git a/cclogconv.go b/cclogconv.go
index e4bf4da..883fc76 100644
--- a/cclogconv.go
+++ b/cclogconv.go
@@ -15,7 +15,7 @@ import (
 func main() {

        var (
-               optMmdbFilePath = flag.String("data", "/usr/share/GeoIP2/GeoLite2-Country.mmdb", "GeoIP2 Database Filename")
+               optMmdbFilePath = flag.String("data", "/tmp/GeoLite2-Country.mmdb", "GeoIP2 Database Filename")
                selectCc        = flag.String("cc", "", "Only displays line including this country's ip")
                nFlag           = flag.Bool("n", false, "Not adding country code")
                vFlag           = flag.Bool("v", false, "Reverse condition for cc option")
cd /tmp
curl -O http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz
gunzip GeoLite2-Country.mmdb.gz

準備OK

使う

  • 未使用時
[PMAC226S ~/src/github.com/rhykw/cclogconv]$ tail -10 access.log
66.249.71.213 - - [29/Jan/2016:21:47:09 +0900] "GET /feed/ HTTP/1.1" 404 168 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
17.142.156.142 - - [29/Jan/2016:21:53:00 +0900] "GET / HTTP/1.1" 200 15817 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Applebot/0.1; +http://www.apple.com/go/applebot)"
66.249.71.213 - - [29/Jan/2016:21:56:09 +0900] "GET /%E3%81%8B%E3%82%81%E3%83%95%E3%83%BC%E3%83%89%E5%A5%BD%E3%81%8D%E4%B8%89%E4%BA%BA%E8%A1%86/ HTTP/1.1" 404 168 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12F70 Safari/600.1.4 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
157.55.39.71 - - [29/Jan/2016:21:56:21 +0900] "GET /robots.txt HTTP/1.1" 404 168 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
157.55.39.71 - - [29/Jan/2016:21:56:26 +0900] "GET / HTTP/1.1" 200 15828 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
185.130.5.244 - - [29/Jan/2016:22:20:26 +0900] "GET /phpmyadmin/scripts/setup.php HTTP/1.0" 404 16 "-" "-"
66.249.71.252 - - [29/Jan/2016:22:26:35 +0900] "GET /?cat=11 HTTP/1.1" 200 15992 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
157.55.39.71 - - [29/Jan/2016:22:59:20 +0900] "GET /%e3%82%ad%e3%83%9c%e3%82%b75/ HTTP/1.1" 404 168 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
66.249.71.234 - - [29/Jan/2016:23:14:35 +0900] "GET /?m=201509 HTTP/1.1" 200 16072 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
184.105.139.68 - - [29/Jan/2016:23:22:49 +0900] "GET / HTTP/1.1" 200 15828 "-" "-"
  • かませてみる
[PMAC226S ~/src/github.com/rhykw/cclogconv]$ tail -10 access.log | ./cclogconv
US 66.249.71.213 - - [29/Jan/2016:21:47:09 +0900] "GET /feed/ HTTP/1.1" 404 168 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
US 17.142.156.142 - - [29/Jan/2016:21:53:00 +0900] "GET / HTTP/1.1" 200 15817 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko) Version/8.0.2 Safari/600.2.5 (Applebot/0.1; +http://www.apple.com/go/applebot)"
US 66.249.71.213 - - [29/Jan/2016:21:56:09 +0900] "GET /%E3%81%8B%E3%82%81%E3%83%95%E3%83%BC%E3%83%89%E5%A5%BD%E3%81%8D%E4%B8%89%E4%BA%BA%E8%A1%86/ HTTP/1.1" 404 168 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12F70 Safari/600.1.4 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
US 157.55.39.71 - - [29/Jan/2016:21:56:21 +0900] "GET /robots.txt HTTP/1.1" 404 168 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
US 157.55.39.71 - - [29/Jan/2016:21:56:26 +0900] "GET / HTTP/1.1" 200 15828 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
LT 185.130.5.244 - - [29/Jan/2016:22:20:26 +0900] "GET /phpmyadmin/scripts/setup.php HTTP/1.0" 404 16 "-" "-"
US 66.249.71.252 - - [29/Jan/2016:22:26:35 +0900] "GET /?cat=11 HTTP/1.1" 200 15992 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
US 157.55.39.71 - - [29/Jan/2016:22:59:20 +0900] "GET /%e3%82%ad%e3%83%9c%e3%82%b75/ HTTP/1.1" 404 168 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)"
US 66.249.71.234 - - [29/Jan/2016:23:14:35 +0900] "GET /?m=201509 HTTP/1.1" 200 16072 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
US 184.105.139.68 - - [29/Jan/2016:23:22:49 +0900] "GET / HTTP/1.1" 200 15828 "-" "-"

使いみち

たとえば、便利だと思うのが中国からきてるIPをまるっと弾きたいとき

[PMAC226S ~/src/github.com/rhykw/cclogconv]$ cat access.log | ./cclogconv | grep '^CN' | awk '{print $2}' | sort | uniq
101.254.204.65
171.214.248.34
180.76.15.13
180.76.15.135
180.76.15.136
180.76.15.137
180.76.15.141
180.76.15.143
180.76.15.147
180.76.15.155
180.76.15.157
180.76.15.162
180.76.15.17
180.76.15.19
180.76.15.22
180.76.15.31
180.76.15.6
180.97.106.161
202.46.50.12
222.191.236.114

かんたんに取り出せる。

シェルスクリプトで巨大な文字列とのマッチング処理をするとき、変数格納よりもファイル参照したほうが速かった

この前必要があってお粗末なスクリプトを書いた時、速度に大きな差があったので気になった。

なんとなく変数に持ったほうが、試行回数が増えるほど早くなるのかとおもってた

宣伝

tapira.hatenablog.com

今回の環境

KagoyaVPS 最小構成CentOS6.5 日毎課金なので特にこだわりなければ安くあがっておすすめです。ちょっと触ってすぐ削除するような使い方

[root@v8794 work]# cat /proc/cpuinfo | grep processor
processor   : 0
processor   : 1
processor   : 2
[root@v8794 work]# cat /etc/redhat-release
CentOS release 6.5 (Final)
[root@v8794 work]# free
             total       used       free     shared    buffers     cached
Mem:       2097152     445288    1651864          0          0     424992
-/+ buffers/cache:      20296    2076856
Swap:      4194304      21420    417288

使用するファイル

# ファイルに対してgrep
[root@v8794 work]# cat file.sh
#! /bin/sh

cat << EOF | while read txt
`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n $2 | sort | uniq`
EOF
do

grep ${txt} $1

if [ $? -eq 0 ]; then
    echo "true"
else
    echo "false"
fi

done

# 変数に格納したあとgrep
[root@v8794 work]# cat val.sh
#! /bin/sh

testtxt=`cat $1`

cat << EOF | while read txt
`cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n $2 | sort | uniq`
EOF
do

echo $testtxt | grep ${txt}

if [ $? -eq 0 ]; then
    echo "true"
else
    echo "false"
fi

done

ファイル観たほうが速い

[root@v8794 work]# time ./file.sh test.txt 10
false
false
false
false
false
false
false
false
false
false

real    0m0.179s
user    0m0.087s
sys 0m0.085s
[root@v8794 work]# time ./val.sh test.txt 10
false
false
false
false
false
false
false
false
false
false

real    0m51.921s
user    0m45.767s
sys 0m7.232s

ちなみに、小さいファイルにしたら逆転するのかと思ったら、そんなことなかった

[root@v8794 work]# ll test2.txt
-rw-r--r-- 1 root root    17000  123 20:48 2016 test2.txt

[root@v8794 work]# time ./file.sh test2.txt 10
false
false
false
false
false
false
false
false
false
false

real    0m0.019s
user    0m0.002s
sys 0m0.007s
[root@v8794 work]# time ./val.sh test2.txt 10
false
false
false
false
false
false
false
false
false
false

real    0m0.049s
user    0m0.032s
sys 0m0.008s
[root@v8794 work]

あれ?これって当たり前の話??? もしかして恥ずかしい疑問なのかもしれない

最近便利だと思ってよく使うコマンドとか

すぐ忘れるので備忘録

コマンドの実行結果を一時ファイルを作成せずにdiffる

[root@v8794 nginx]# diff -u nginx.conf <(sed 's/kame/hoge/g' nginx.conf)
--- nginx.conf    2016-01-17 18:04:41.000000000 +0900
+++ /dev/fd/63    2016-01-23 00:43:56.601767533 +0900
@@ -9,17 +9,17 @@
     keepalive_timeout   65;
     server {
         listen       80;
-        server_name  kame.photos;
+        server_name  hoge.photos;
         location / {
-            root   /var/www/kame;
+            root   /var/www/hoge;
             index  index.php;
         }

         location ~ \.php$ {
-            root /var/www/kame;
+            root /var/www/hoge;
             fastcgi_pass   127.0.0.1:9000;
             fastcgi_index  index.php;
-            fastcgi_param  SCRIPT_FILENAME  /var/www/kame$fastcgi_script_name;
+            fastcgi_param  SCRIPT_FILENAME  /var/www/hoge$fastcgi_script_name;
             include        fastcgi_params;
         }

@@ -31,19 +31,19 @@
         ssl_protocols TLSv1.2;
         #ssl_session_timeout  5m;

-        ssl_certificate      /etc/letsencrypt/live/kame.photos/fullchain.pem;
-        ssl_certificate_key  /etc/letsencrypt/live/kame.photos/privkey.pem;
+        ssl_certificate      /etc/letsencrypt/live/hoge.photos/fullchain.pem;
+        ssl_certificate_key  /etc/letsencrypt/live/hoge.photos/privkey.pem;

         location / {
-            root    /var/www/kame;
+            root    /var/www/hoge;
             index   index.php;
         }

    location ~ \.php$ {
-            root /var/www/kame;
+            root /var/www/hoge;
             fastcgi_pass   127.0.0.1:9000;
             fastcgi_index  index.php;
-            fastcgi_param  SCRIPT_FILENAME  /var/www/kame$fastcgi_script_name;
+            fastcgi_param  SCRIPT_FILENAME  /var/www/hoge$fastcgi_script_name;
             include        fastcgi_params;
        }

<( command ) の結果に /dev/fd/63 とファイルディスクリプタが割り当てられている

↑を応用して、find&replaceの確認

たとえば、あるディレクトリ以下のphpでおわるファイルの中身を wp -> KAME に変更する際に、想定のファイルが想定の部分だけ変更されるか、をチェックする。

[root@v8794 widgets]# for x in `find . -type f`; do diff -u $x <(sed 's/wp/KAME/g' $x); done
--- ./class-wp-widget-calendar.php  2015-09-27 10:07:25.000000000 +0900
+++ /dev/fd/63 2016-01-23 01:24:20.132003630 +0900
@@ -48,7 +48,7 @@
     * @param array $instance The settings for the particular instance of the widget.
     */
    public function widget( $args, $instance ) {
-       /** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
+       /** This filter is documented in KAME-includes/widgets/class-KAME-widget-pages.php */
        $title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );

        echo $args['before_widget'];
@@ -94,7 +94,7 @@
     * @param array $instance Current settings.
     */
    public function form( $instance ) {
-       $instance = wp_parse_args( (array) $instance, array( 'title' => '' ) );
+       $instance = KAME_parse_args( (array) $instance, array( 'title' => '' ) );
        $title = sanitize_text_field( $instance['title'] );
        ?>
        <p><label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?></label>
--- ./class-wp-nav-menu-widget.php  2015-09-29 00:31:25.000000000 +0900
+++ /dev/fd/63 2016-01-23 01:24:20.134003626 +0900
@@ -39,12 +39,12 @@
     */
    public function widget( $args, $instance ) {
        // Get menu
-       $nav_menu = ! empty( $instance['nav_menu'] ) ? wp_get_nav_menu_object( $instance['nav_menu'] ) : false;
+       $nav_menu = ! empty( $instance['nav_menu'] ) ? KAME_get_nav_menu_object( $instance['nav_menu'] ) : false;

        if ( !$nav_menu )
            return;

-       /** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
+       /** This filter is documented in KAME-includes/widgets/class-KAME-widget-pages.php */
        $instance['title'] = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'], $instance, $this->id_base );

        echo $args['before_widget'];
@@ -64,7 +64,7 @@
         * @since 4.4.0 Added the `$instance` parameter.
         *
         * @param array    $nav_menu_args {
-        *     An array of arguments passed to wp_nav_menu() to retrieve a custom menu.
+        *     An array of arguments passed to KAME_nav_menu() to retrieve a custom menu.
         *
         *     @type callable|bool $fallback_cb Callback to fire if the menu doesn't exist. Default empty.
       *     @type mixed         $menu        Menu ID, slug, or name.
@@ -73,7 +73,7 @@
       * @param array    $args          Display arguments for the current widget.
       * @param array    $instance      Array of settings for the current widget.
       */
-     wp_nav_menu( apply_filters( 'widget_nav_menu_args', $nav_menu_args, $nav_menu, $args, $instance ) );
+     KAME_nav_menu( apply_filters( 'widget_nav_menu_args', $nav_menu_args, $nav_menu, $args, $instance ) );

      echo $args['after_widget'];

同じパターンのファイルを大量に生成する

cat << EOF > xxx.txtcat << EOF | command1 | command2 が、一時ファイルを用意せず色々やれてすき

[root@v8794 sample]# for x in `seq 1 100`; do cat << EOF | sed "s/_PLACEHOLDER_/for_${x}_replace/g" > work/${x}.txt
<html>
  <head>_PLACEHOLDER_</head>
  <body>
    _PLACEHOLDER_XXXXXXXXXXXXXXXXXXXXX
  </body>
</html>

EOF
; done

[root@v8794 sample]# ls -lt work/
合計 400
-rw-r--r-- 1 root root 109  123 01:02 2016 1.txt
-rw-r--r-- 1 root root 109  123 01:02 2016 10.txt
-rw-r--r-- 1 root root 109  123 01:02 2016 100.txt
-rw-r--r-- 1 root root 109  123 01:02 2016 11.txt
-rw-r--r-- 1 root root 109  123 01:02 2016 12.txt
-rw-r--r-- 1 root root 109  123 01:02 2016 13.txt
-rw-r--r-- 1 root root 109  123 01:02 2016 14.txt
-rw-r--r-- 1 root root 109  123 01:02 2016 15.txt
-rw-r--r-- 1 root root 109  123 01:02 2016 16.txt
-rw-r--r-- 1 root root 109  123 01:02 2016 17.txt
-rw-r--r-- 1 root root 109  123 01:02 2016 18.txt
-rw-r--r-- 1 root root 109  123 01:02 2016 19.txt
-rw-r--r-- 1 root root 109  123 01:02 2016 2.txt
-rw-r--r-- 1 root root 109  123 01:02 2016 20.txt

[root@v8794 sample]# cat work/1.txt
<html>
  <head>for_1_replace</head>
  <body>
    for_1_replaceXXXXXXXXXXXXXXXXXXXXX
  </body>
</html>

予め定められたリストにマッチした場合に、規定値を使用して処理する

#! /bin/sh

DATA="
01  AAAAAAAAAAAAAAAAA tanaka
02  BBBBBBBBBBBBBBBBB ikeda
03  CCCCCCCCCCCCCCCCC yamada
"

d=$(echo "${DATA}" | grep $1)

read no txt user <<< "${d}"

echo $no
echo $txt
echo $user

量が多くなるのであればDBなど使用するほうがよいが、小さなプログラムに便利。

read x y z <<< $val もすき。