読者です 読者をやめる 読者になる 読者になる

今更ながら標準出力と標準エラー出力について

 ども。
 「西尾張、南濃界隈にweb系インフラの需要は無いのかっ!」と思いつつ勉強会行ったり求職活動したり、実家で穀を潰したりしているアラフォーの、
 kwy です。


 今回は掲題の通り今更ながらの標準出力と標準エラー出力について。
 恥ずかしながら私これまであまり標準出力と標準エラー出力を区別してなかったんですよね。待って! 椅子投げるのはちょっと待って(古いけど出典は いい加減、>/dev/null 2>&1と書くのをやめたらどうか (追記あり) · DQNEO起業日記 を発端とする諸々のブログエントリです)!

 個人的には、「標準出力も標準エラー出力も全部同じログに書いときゃいいじゃない。テキストなんて大した容量じゃないんだし」と考えていたのですが、過日、愛知県立図書館で借りてきた『UNIXという考え方 その設計思想と哲学』という本をパラパラめくっていると

エラーメッセージやその他の警告は、stderr経由でユーザーに送るべきだ。stdout宛てのデータストリームに混在させてはならない。その理由の一つは、エラーメッセージだけを別ファイルに保存したり、直ちに端末上に表示したりと、ユーザーごとに対応が異なるからだ。エラーメッセージをエラーメッセージをstdoutとして同じ入出力チャネルで送ることは、後に続く作業で混乱を招きかねない。

という一文を見かけ、なるほどそれも一理ある。あと、前述の「テキストなんて大した容量」云々、は、ちょっと富豪的思想だなぁと反省した次第。

とは言え個人的には、「一ファイルに標準出力も標準エラー出力(stderr)もまとめて出力して、時系列で終えるようにする」の方が好みなんですが、まぁそこは解析時に結合するのもそんな手間でもないし、標準出力&標準エラー出力ファイルとは別に標準エラー出力だけのファイル作ってみてもいいし、そもそも別ファイルにしたこと無いし、試してみようかななんて思ったり。


 ようやく本題。+nixでの標準出力/標準エラー出力についてのメモ。
 まずは標準出力(1)

$ sh ./hoge.sh 1> fuga.txt

 ちょっと捻ると

$ sed -e "s/hoge/fuga/g" foobar.txt 2> dev/null

 とすれば、標準出力(デフォルトだとターミナル)だけを取り出せる。

 標準エラー出力(2)だと

$ sh ./hoge.sh 2> fuga-err.txt

 合わせ技で

$ sh ./hoge.sh 1> fuga-normal 2> fuga-err 

になる。

 あれ? 結局元エントリ( いい加減、>/dev/null 2>&1と書くのをやめたらどうか (追記あり) · DQNEO起業日記 )と同じ所に着地してる……。

今更ながら標準出力と標準エラー出力について

 ども。  「西尾張、南濃界隈にweb系インフラの需要は無いのかっ!」と思いつつ勉強会行ったり求職活動したり、実家で穀を潰したりしているアラフォーの、  kwy です。


 今回は掲題の通り今更ながらの標準出力と標準エラー出力について。
 恥ずかしながら私これまであまり標準出力と標準エラー出力を区別してなかったんですよね。待って! 椅子投げるのはちょっと待って(古いけど出典は

いい加減、>/dev/null 2>&1と書くのをやめたらどうか (追記あり) · DQNEO起業日記 を発端とする諸々のブログエントリです)!

 個人的には、「標準出力も標準エラー出力も全部同じログに書いときゃいいじゃない。テキストなんて大した容量じゃないんだし」と考えていたのですが、過日、愛知県立図書館で借りてきた『UNIXという考え方 その設計思想と哲学』という本をパラパラめくっていると

エラーメッセージやその他の警告は、stderr経由でユーザーに送るべきだ。stdout宛てのデータストリームに混在させてはならない。その理由の一つは、エラーメッセージだけを別ファイルに保存したり、直ちに端末上に表示したりと、ユーザーごとに対応が異なるからだ。エラーメッセージをエラーメッセージをstdoutとして同じ入出力チャネルで送ることは、後に続く作業で混乱を招きかねない。  という一文を見かけ、なるほどそれも一理ある。あと、前述の「テキストなんて大した容量」云々、は、ちょっと富豪的思想だなぁと反省した次第。

 とは言え個人的には、「一ファイルに標準出力も標準エラー出力(stderr)もまとめて出力して、時系列で終えるようにする」の方が好みなんですが、まぁそこは解析時に結合するのもそんな手間でもないし、標準出力&標準エラー出力ファイルとは別に標準エラー出力だけのファイル作ってみてもいいし、そもそも別ファイルにしたこと無いし、試してみようかななんて思ったり。

 ようやく本題。+nixでの標準出力/標準エラー出力についてのメモ。
 まずは標準出力(1)

$ sh ./hoge.sh 1> fuga.txt

 別の書き方としては

$ sed -e "s/hoge/fuga/g" foobar.txt 2> dev/null

Scientific Linuxにおけるbonding設定(NetworkManager = not networkの場合)

 モジュールの起動確認は前回と同じ

# lsmod |grep bond
# modprobe --first-time bonding
# lsmod |grep bond
bonding               136630  0

 NetworkManager自体はRHEL7系からの推奨で、かつ、nmcliというCLIで設定をおこなうらしい。設定情報がどこに格納されるのかは未確認。 * まずは事前の情報化国な

# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:b3:23:42 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.50/24 brd 192.168.0.255 scope global enp0s3
       valid_lft forever preferred_lft forever
    inet6 2402:6b00:4017:1800:a00:27ff:feb3:2342/64 scope global noprefixroute dynamic
       valid_lft 286sec preferred_lft 286sec
    inet6 fe80::a00:27ff:feb3:2342/64 scope link
       valid_lft forever preferred_lft forever
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:cf:f3:c4 brd ff:ff:ff:ff:ff:ff

 で、コチラが噂のcliでみた結果。

# nmcli c
名前    UUID                                  タイプ          デバイス
enp0s8  6d2589d4-2fd4-40bd-929e-2681b45ebc4b  802-3-ethernet  --
enp0s3  995d3887-9fd0-4596-9e78-cbf2d25d7449  802-3-ethernet  enp0s3

 確かに、s3は起動していて、s8は起動していない。

  • で、ここにボンディングデバイスを追加する。
# nmcli connection add type bond autoconnect no con-name bond0 ifname bond0 mode active-backup
接続 'bond0' (1a75769d-b348-4ac8-a438-ec8f0e9a634e) が正常に追加されました。
# nmcli c
名前    UUID                                  タイプ          デバイス
enp0s8  6d2589d4-2fd4-40bd-929e-2681b45ebc4b  802-3-ethernet  --
enp0s3  995d3887-9fd0-4596-9e78-cbf2d25d7449  802-3-ethernet  enp0s3
bond0   1a75769d-b348-4ac8-a438-ec8f0e9a634e  bond            --

起動していないデバイスをbond0に引っ掛ける

# nmcli connection add type bond-slave autoconnect no ifname enp0s8 master bond0
接続 'bond-slave-enp0s8' (8e8852bf-f180-4f34-98f0-09731e9600bd) が正常に追加されました。

# nmcli c
名前               UUID                                  タイプ          デバイ ス
enp0s8             6d2589d4-2fd4-40bd-929e-2681b45ebc4b  802-3-ethernet  --     
enp0s3             995d3887-9fd0-4596-9e78-cbf2d25d7449  802-3-ethernet  enp0s3 
bond-slave-enp0s8  8e8852bf-f180-4f34-98f0-09731e9600bd  802-3-ethernet  --     
bond0              1a75769d-b348-4ac8-a438-ec8f0e9a634e  bond            --     

 下記出力をみると、bond0のslaveになっていることが確認できる。

# nmcli -f connection c s bond-slave-enp0s8
connection.id:                          bond-slave-enp0s8
connection.uuid:                        8e8852bf-f180-4f34-98f0-09731e9600bd
connection.interface-name:              enp0s8
connection.type:                        802-3-ethernet
connection.autoconnect:                 no
connection.autoconnect-priority:        0
connection.timestamp:                   0
connection.read-only:                   no
connection.permissions:
connection.zone:                        --
connection.master:                      bond0
connection.slave-type:                  bond
connection.autoconnect-slaves:          -1 (default)
connection.secondaries:
connection.gateway-ping-timeout:        0
connection.metered:                     不明

 bondingデバイスにIPアドレスなどを設定する。

# nmcli -f ipv4 c s bond0
ipv4.method:                            auto
ipv4.dns:
ipv4.dns-search:
ipv4.addresses:
ipv4.gateway:                           --
ipv4.routes:
ipv4.route-metric:                      -1
ipv4.ignore-auto-routes:                no
ipv4.ignore-auto-dns:                   no
ipv4.dhcp-client-id:                    --
ipv4.dhcp-send-hostname:                yes
ipv4.dhcp-hostname:                     --
ipv4.never-default:                     no
ipv4.may-fail:                          yes

# LANG=C ; nmcli c e bond0

===| nmcli interactive connection editor |===

Editing existing 'bond' connection: 'bond0'

Type 'help' or '?' for available commands.
Type 'describe [<setting>.<prop>]' for detailed property description.

You may edit the following settings: connection, bond, 802-3-ethernet (ethernet), ipv4, ipv6
nmcli> set ipv4.method manual
nmcli> set ipv4.dns 192.168.0.1
nmcli> set ipv4.addresses 192.168.0.51/24
nmcli> p ipv4
['ipv4' setting values]
ipv4.method:                            manual
ipv4.dns:                               192.168.0.1
ipv4.dns-search:
ipv4.addresses:                         192.168.0.51/24
ipv4.gateway:                           --
ipv4.routes:
ipv4.route-metric:                      -1
ipv4.ignore-auto-routes:                no
ipv4.ignore-auto-dns:                   no
ipv4.dhcp-client-id:                    --
ipv4.dhcp-send-hostname:                yes
ipv4.dhcp-hostname:                     --
ipv4.never-default:                     no
ipv4.may-fail:                          yes
nmcli>
nmcli> verify
Verify connection: OK
nmcli> save
Connection 'bond0' (1a75769d-b348-4ac8-a438-ec8f0e9a634e) successfully updated.
nmcli> quit

 アクティブスタンバイ構成なので、s8はONBOOT=yesに変更する。(s3はいじらない)

# cp -ipr --parents /etc/sysconfig/network-scripts/ifcfg-bond-slave-enp0s8 /var/tmp/infrawork/bkup/
# cp -ipr --parents /etc/sysconfig/network-scripts/ifcfg-bond0 /var/tmp/infrawork/bkup/
# sed -i -e 's/ONBOOT=no/ONBOOT=yes/' /etc/sysconfig/network-scripts/ifcfg-bond-slave-enp0s8
# sed -i -e 's/ONBOOT=no/ONBOOT=yes/' /etc/sysconfig/network-scripts/ifcfg-bond0
# nmcli c m enp0s8 connection.autoconnect no
# systemctl restart NetworkManager.service ; nmcli c up bond-slave-enp0s8
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/3)

# nmcli connection add type bond-slave ifname enp0s3 master bond0
Connection 'bond-slave-enp0s3' (0b5d165d-8695-4070-8426-8d40d0084968) successfully added.
# nmcli c
NAME               UUID                                  TYPE            DEVICE
bond0              1a75769d-b348-4ac8-a438-ec8f0e9a634e  bond            bond0
bond-slave-enp0s8  8e8852bf-f180-4f34-98f0-09731e9600bd  802-3-ethernet  enp0s8
enp0s3             995d3887-9fd0-4596-9e78-cbf2d25d7449  802-3-ethernet  enp0s3
bond-slave-enp0s3  0b5d165d-8695-4070-8426-8d40d0084968  802-3-ethernet  --
enp0s8             6d2589d4-2fd4-40bd-929e-2681b45ebc4b  802-3-ethernet  --

# cat /proc/net/bonding/bond0
MII Status: down
MII Polling Interval (ms): 0
Up Delay (ms): 0
Down Delay (ms): 0
# cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)

Bonding Mode: fault-tolerance (active-backup)
Primary Slave: None
Currently Active Slave: enp0s8
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 0
Down Delay (ms): 0

Slave Interface: enp0s8
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: 08:00:27:cf:f3:c4
Slave queue ID: 0

# init 6

 と、ここまで書いたところで噂が聞こえてきたのだが、RHEL7系からはインストール時にボンディング設定ができるとかなんとか……。まじかー。

 また、これとは別に、/etc/sysconfig/networkにHOSTNAME=hogeしても、ホスト名は変わらなかったりと、いろいろ厄介そうだ。

Scientific Linuxにおけるbonding設定(network = not NetworkManagerの場合)

e-words.jp

 と、いうわけでNIC2つを1つにまとめるbondingをやってみる。


  • まずはbondingに必要なモジュールが読み込まれていることを確認する
# lsmod |grep bond
# 

 ……。読み込まれて、いない。と。

# modprobe --first-time bonding
# lsmod |grep bond
bonding               136630  0

 これで読み込まれた。と。


 旧来のRHEL系OSでは、networkというサービスがネットワーク機能を管理していたのだが、RHEL6(だったと思う)から、NetworkManagerというサービスに置き換えられるようになった。個人的にはNetworkManagerは嫌いで(個人の見解です)、RHEL6まではNetworkManagerを止めて、networkを使うようにしていたのだが、RHEL7以降はNetworkManagerが推奨とかいう噂もちらほら聞こえたり。とりあえず両方のやり方をおさらい。

  • networkを使用している場合
# systemctl stop NetworkManager.service && systemctl start network

 まぁ1回こっきりなので、systemctl enableはしない。続いて設定ファイルを

# vi /etc/sysconfig/network-scripts/ifcfg-bond0

 内容は

DEVICE=bond0
NAME=bond0
TYPE=Bond
BONDING_MASTER=yes
BOOTPROTO="none"
IPADDR=192.168.0.50
PREFIX=24
GATEWAY=192.168.0.1
DNS1=192.168.0.1
ONBOOT=yes
BONDING_OPTS="mode=1 miimon=100"
NM_CONTROLLED=no
# vi /etc/sysconfig/network-scripts/ifcfg-ethX

 まぁファイル名は違うけどご愛嬌。コッチの内容は

TYPE="Ethernet"
BOOTPROTO="none"
NAME="ethX"
DEVICE="ethX"
ONBOOT="yes"
MASTER=bond0
SLAVE=yes

 2枚目のNICの設定ファイルも同内容。

 これでサービス再起動すればbondingが有効になる。はず……(ごめんなさい今回作業ログをもとに書いているので間違いがあるかも……)。


 NetworkManagerの場合はまた次回。

続・続・検証で使うCentOS7初期設定

 前回の最後で書いたように、現状アンチウィルスソフトが一切入っていません。これがデータセンターに入ってるサーバーだったら、UTM機器やらなんやらで、サーバーに届く前にいろいろ対処されるんだろうけど、コイツはしがない自宅サーバー。お高い防具なぞ買えません。

 と、いうわけで今回は無償のアンチウィルスソフトを入れてみる、というお話。


 何年か前に、Macなんかでも使える、"Sophos Antivirus"がLinuxでも使えるようになったなんて話を聞いたなぁ……。などと思いつつ、定番のClamAVを入れてみることに。

# rpm -ivh http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el7.rf.x86_64.rpm
# yum -y install clamd
# cp -ipr --parents /etc/clamd.conf /var/tmp/infrawork/bkup/
# vi /etc/clamd.conf
# diff /etc/clamd.conf /var/tmp/infrawork/bkup/etc/clamd.conf
165,166c165,166
< ExcludePath ^/proc/
< ExcludePath ^/sys/
---
> #ExcludePath ^/proc/
> #ExcludePath ^/sys/
195c195
< # User clamav
---
> User clamav
# systemctl start clamd
# systemctl enable clamd
# freshclam
# mkdir  /var/log/clamav-scan-log
# chmod  666  /var/log/clamav-scan-log 
# cd  /etc/cron.daily
# vi clamscan

clamscanの内容は

#!/bin/sh
yum update -y --enablerepo=rpmforge clamd
clamscan / -r --remove --exclude-dir='/sys|/proc|/dev' > /var/log/clamav-scan-log/`date +%Y%m%d`.log
tail -10 /var/log/clamav-scan-log/`date +%Y%m%d`.log

とする。で、

# chmod 755 clamscan

 これでおしまい。ざっくりしているのは、参考にさせていただいた下記サイトの内容をほぼ書き写しているだけだから。

www.totsusangyo.com

 clamavって、clamdと名前が変わっていたんだなぁ。


 さて次は何をしよう。リハビリなんだからLAMP環境でも作るか、それともZabbixとかを入れる方に進むか……。

続・検証で使うCentOS7初期設定

あー、昨日書き忘れたけど常時GUI動かすわけではないので、

# cp -ipr --parents /etc/inittab /var/tmp/infrawork/bkup
# sed -i -e 

と思ったらsystemdになってinittabって廃止になったのね。考えてみりゃinitdがsystemdになったんだから、そりゃそーか。

# systemctl get-default` 
graphical.target

なんてちょろいこと言ってくれちゃうので、 # systemctl set-default multi-user.target とすればいいみたい。うわー、initコマンドが普通に使えてたから気づかんかったわ…。 ちなみに全部systemctlが担当するなら、telinitに相当するのはなんだろう……?

 あと、/var/tmp/infrawork/log/historyディレクトリ作り忘れてるので

# mkdir /var/tmp/infrawork/log/history
# chmod 777 /var/tmp/infrawork/log/history

しとかないとね

以上、閑話休題


  • VNC(ではなくxrdp)の設定
     当初はVNCにしようと思ったのだけど、Windowsからのリモートデスクトップ接続が使えるxrdpというものが存在するらしいので、まぁそっちの方がクライアント側がお手軽だなぁということで、xrdpを使用することに。
# yum -y install epel-release
# yum -y install xrdp tigervnc-server
# systemctl start xrdp.service
# systemctl enable xrdp.service

これでxrdpが使用できるようになる。SELINUXが有効な場合は更に処理がいるようだけれども今回は省略。


  • 仮想化環境の構築  これも当初はKVM仮想マシンマネージャの併用で行こうと思ったんだけど、昔、ブリッジインターフェースを設定するのにひどく苦労した記憶があるので、スピード重視の今回は断念。さくっとブリッジ接続できるVirtualBoxをインストールすることにした。
# cd /var/tmp/infrawork/rpm/
# wget http://download.virtualbox.org/virtualbox/5.0.20/VirtualBox-5.0-5.0.20_106931_fedora18-1.x86_64.rpm
# yum -y install ./VirtualBox-5.0-5.0.20_106931_fedora18-1.x86_64.rpm

yumコマンドのこの使い方、前職で初めて知ったんだよなぁ。便利。
 と、いうのはおいておいて、実はこの状態だと、CentOS7のカーネルが古すぎてVirtualBoxが動かない。厳密には仮想マシンを動作させようとするとエラーで止まる。
 そのため、カーネルのバージョンを上げる。

# wget http://download.virtualbox.org/virtualbox/rpm/rhel/virtualbox.repo
# yum -y install kernel-devel kernel-headers dkms
# yum groupinstall "Development Tools"
# yum update
# init 6

再起動後、一般ユーザーでログインして、エラーメッセージにあったとおり、
# /sbin/rcvboxdrv setup
としてやれば動くようになる。


 とりあえず焦らず今日はここまで。よく考えたらアンチウィルスソフト入れてない……。順序は前後するが、明日はそれをやろう……。

検証で使うCentOS7初期設定

 復職を狙うどころか、求職をせねばならない身になったこともあり、リハビリがてら家のDELL PRECISIONにCentOSをぶち込んで、SSH/VNC越しに色々やってみることにした。
 まぁVNCは使うかどうかわからないけど、仮想化まわりの検証で使いそうだったもので。

Markdownがちゃんとかけなかったので、いったんこのままで公開。

(そしてたぶんこのままほっとかれる)

---
* やったこと

1. OSインストール
メディアからGUIインストール。注意した点は

* ディスク構成を変えて、/homeを消して/boot, /, swapだけにする(仮想マシン作る時のディスク容量欲しいし)
* ネットワーク構成はあらかじめ固定IPを指定しておく(ホームネットワークだから開いてるのを適当に)
* 念のため、GNOME Desktopの標準構成にしたら、インストール後の再起動時、ログイン前にEULAへの同意を求めるアイコンが出たこと。あとkdump設定も出たけどこれは前からな気がする。まぁEULAは同意、kdumpは無効にしとけばいいかと。
というくらい


2. とりあえず初期設定で使うgit. wgetを入れる
# yum -y install git wget

 

3. 初期設定に使うスクリプトを持ってくる

# git clone https://github.com/kwy8791/system_tools.git

↑これ現状では使いものにならないから直すし下のも入れるし自動化したい。

 

4. 初期設定を行う

# cd system_tools/
# ./post_install_OS.sh
↑これ現状では使いものにならないから直すし下のも入れるし自動化したい。

# mkdir -p /var/tmp/infrawork/{src,log,rpm,bkup}
# mkdir /var/tmp/infrawork/src/{archived,extraceted}

# cp -ip --parents /etc/selinux/config /var/tmp/infrawork/bkup
# sed -i -e "s/SELINUX=enforcing/SELINUX=disabled/" /etc/selinux/config
# cp -ip --parents /etc/yum.conf /var/tmp/infrawork/bkup
sed -i -e "s/^keepcache=0/keepcache=1/" /etc/yum.conf

# cp -ip /etc/profile /var/tmp/infrawork/bkup
# cat <<- EOF >> /etc/profile

# history command environment
export HISTTIMEFORMAT='%y/%m/%d %H:%M:%S ';
export HISTFILESIZE=
export HISTSIZE=
EOF
# echo '/bin/script /var/tmp/infrawork/log/history/`date +%Y%m%d-%H%M%S`-${USER}.log' >> /etc/profile

# yum -y upgrade

 

5. sudo設定

# visudo

設定内容はお好みで

 

6. rootによるSSHログインの停止

# cp -ipr --parents /etc/ssh/sshd_config /var/tmp/infrawork/bkup/
# sed -i -e "s/^#PermitRootLogin yes/PermitRootLogin no/" /etc/ssh/sshd_config

 

7. とりあえずSSH/HTTP/HTTPS/VNCを通すようにfirewalldを設定する

# firewall-cmd --permanent --zone=public --add-port=22/tcp
# firewall-cmd --permanent --zone=public --add-port=80/tcp
# firewall-cmd --permanent --zone=public --add-port=443/tcp
# firewall-cmd --permanent --zone=public --add-port=3389/tcp

 ---

ちょっと疲れたので次はVNCの設定は別途。

SELINUXの設定をいじったので、

# reboot

して、続きは明日かな。