2013年2月24日日曜日

NIC の ifup の際に eth パラメータを調整したい

CentOS 6 において、サーバ起動時の eth0 初期化時に、ethtool による調整を行いたいのですが、/etc/sysconfig/network-scripts/ifcfg-eth0 に指定可能な ETHTOOL_OPTS は、ethtool -s に対応しており、それ以外の ethtool 調整には対応していません。今回、ethtool -G による調整を行いたかった為、その方法について調べてみました。
真っ先に思いつく方法は、rc.local に書いてしまえばいいということなんですが、/sbin/ifup の内容を読んでみると、ローカルな設定を行えるようにする仕掛けがありました。次は、ifup から抜粋です。
...

if [ -x /sbin/ifup-pre-local ]; then
    /sbin/ifup-pre-local ${CONFIG} $2
fi

OTHERSCRIPT="/etc/sysconfig/network-scripts/ifup-${DEVICETYPE}"

if [ ! -x ${OTHERSCRIPT} ]; then
    OTHERSCRIPT="/etc/sysconfig/network-scripts/ifup-eth"
fi

exec ${OTHERSCRIPT} ${CONFIG} $2

ということは、自分で /sbin/ifup-pre-local を用意すれば、所望の設定が出来そうです。次のような具合。
#!/bin/bash

DEV=${1/ifcfg-/}

if [ "$DEV" = "eth0" ] ; then
    ethtool -G $DEV rx 4096 tx 4096 2>/dev/null
fi
これで、うまくいきました。
# ethtool -g eth0
Ring parameters for eth0:
Pre-set maximums:
RX:  4096
RX Mini: 0
RX Jumbo: 0
TX:  4096
Current hardware settings:
RX:  4096
RX Mini: 0
RX Jumbo: 0
TX:  4096

この黄色の部分を調整したかった。

2013-02-26追記
匿名さま、コメント(Bugzilla情報)をありがとうございました。ifcfg-eth0 に次のように指定すれば、ethtool -G も指定可能だったのですね。確認足りませんでした。orz
ETHTOOL_OPTS="-G \$REALDEVICE rx 4096 tx 4096"

2013-02-27追記
匿名さま、たびたびコメントを頂きありがとうございました。network-functions を見てみたら、ご指摘のとおり、eval のアイデアは取り込まれておりませんでした。というわけで、こうなってしまうのですね。
ETHTOOL_OPTS="-G eth0 rx 4096 tx 4096"
コピーして間違いを犯しそうではありますが。。

2013年1月17日木曜日

CentOS6 の cron.daily 実行時刻を CentOS5 以前と同様に設定する

CentOS6 の cron.daily 実行時刻は、CentOS5 以前とは異なります。
※この記事に書いた手順は、RHEL8 / RHEL7 / RHEL6でも通用します。末尾参照
CentOS5 以前であれば、デフォルトでは午前4:02にスケジュールされていましたが、CentOS6 のデフォルトでは、ある幅の範囲内でランダム化されています。
まずは、このランダム化の内容を確認してみます。

最初に /etc/crontab を見てみますと、次のように空っぽです。
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed

CentOS5 以前であれば、次のようにエントリーされていました。
02 4 * * * root run-parts /etc/cron.daily

ランダム化は、anacron (cronie-anacron) により行われており、設定内容は /etc/anacrontab に記述されています。デフォルトの /etc/anacrontab は、次の通りです。
# /etc/anacrontab: configuration file for anacron

# See anacron(8) and anacrontab(5) for details.

SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22

#period in days   delay in minutes   job-identifier   command
1       5       cron.daily              nice run-parts /etc/cron.daily
7       25      cron.weekly             nice run-parts /etc/cron.weekly
@monthly 45     cron.monthly            nice run-parts /etc/cron.monthly
いくつかのパラメータがあり、man anacrontab(5) に解説がありますが、概説しますと、赤字の 1 (左端) が実行周期 (日次実行=1) で、次の数字 5 は、実行開始タイミングになってから、5 分間の遅延を入れる指定です。実行開始する時間帯は START_HOURS_RANGE で制御され、3-22 とは、3時から22時までの範囲 (3:00 ≦ t < 22:00) を指定しています。ランダム化の幅は RANDOM_DELAY で制御され、45 とは 0~45 分の範囲 (乱数計算の実装上、正確には 44 分まで) でランダムに遅延を行うことを指定しています。
やや複雑ですが、このデフォルト設定で 24H 運用した場合、cron.daily は午前3:06から3:50の間でランダム実行されることになります。ここで 3:06 なのは、そもそも anacron が動作する周期が毎時01分であるためです。/etc/cron.d/0hourly および /etc/cron.hourly/0anacron 参照。
また、もし毎日シャットダウン電源OFF運用を行う場合、例えば、午前6:00にブートすると、その直後の午前6:06から6:50の間でランダムに cron.daily が実行されることになります。
もしも、1日以上シャットダウンしていて、午後23:00にブートした場合には、START_HOURS_RANGE の範囲外であるため、cron.daily の実行は、翌日の午前3:06から3:50の間ということになります。

このランダム化は、仮想化環境を考慮してのこと (ゲストOSの cron.daily が重ならないようにする意図) とは思いますが、ランダムに動作されるのは運用上よろしくない (混乱要因となる) と考える方も居るかと思います。CentOS6 では、CentOS5 以前のように固定の時刻に cron.daily を行わせるようにする方法も用意されており、デフォルトでインストールされる cronie-anacron パッケージの代わりに、cronie-noanacron をインストールすればよいです。

パッケージの依存関係のため、事前に cronie-noanacron をインストールし、その後に cronie-anacron を削除するという手順を踏みます。
# yum install cronie-noanacron
...途中省略...
Installed:
  cronie-noanacron.x86_64 0:1.4.4-7.el6

Complete!

# rpm -e cronie-anacron
この cronie-noanacron は、ちっぽけなパッケージで、/etc/cron.d/dailyjobs ファイルだけを含んでいます。
# rpm -qi cronie-noanacron                                                   
Name        : cronie-noanacron             Relocations: (not relocatable)
Version     : 1.4.4                             Vendor: CentOS
Release     : 7.el6                         Build Date: Tue 19 Jul 2011 01:55:56 PM JST
Install Date: Thu 17 Jan 2013 12:02:39 AM JST      Build Host: c6b5.bsys.dev.centos.org
Group       : System Environment/Base       Source RPM: cronie-1.4.4-7.el6.src.rpm
Size        : 326                              License: MIT and BSD and ISC and GPLv2
Signature   : RSA/SHA1, Mon 26 Sep 2011 01:17:22 PM JST, Key ID 0946fca2c105b9de
Packager    : CentOS BuildSystem 
URL         : https://fedorahosted.org/cronie
Summary     : Utility for running simple regular jobs in old cron style
Description :
Old style of {hourly,daily,weekly,monthly}.jobs without anacron. No features.

# rpm -ql cronie-noanacron
/etc/cron.d/dailyjobs    ※パッケージの中身はこれ1個
/etc/cron.d/dailyjobs の中身は次のようになっています。
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/

# run-parts
02 4 * * * root [ ! -f /etc/cron.hourly/0anacron ] && run-parts /etc/cron.daily
22 4 * * 0 root [ ! -f /etc/cron.hourly/0anacron ] && run-parts /etc/cron.weekly
42 4 1 * * root [ ! -f /etc/cron.hourly/0anacron ] && run-parts /etc/cron.monthly
CentOS5 以前での運用経験があれば、見慣れた実行時刻かと思います。ただし、0anacron の存在チェックが行われており、cronie-anacron パッケージを削除しないと有効化されないようにガードされています。ご注意を。

すでにお分かりかとは思いますが、cron.weekly および cron.monthly も同様です。ただ、cron.hourly はランダム化されておらず、次のように /etc/cron.d/0hourly に設定が書かれています。
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
01 * * * * root run-parts /etc/cron.hourly

最後に、いわずもがなですが、RHEL6 でも同様です :-p

2013-01-18追記
境界値がはっきりしないので、いちおう cronie-1.4.4-7.el6 のソースを見てみました。

START_HOURS_RANGE に対応する処理は、次の通りです。こちらは簡単ですね。
    422             t = localtime(&jobtime);
    423             if (range_start != -1 && range_stop != -1 &&
    424                 (t->tm_hour < range_start || t->tm_hour >= range_stop))
    425             {
    426                 Debug(("The job `%s' falls out of the %02d:00-%02d:00 hours range, skipping.",
    427                         job_array[j]->ident, range_start, range_stop));
    428                 job_array[j]->drop_job = 1;
    429             }
    430             else
"anacron/main.c"

RANDOM_DELAY に対応する処理は、次の通りです。
    279         if (strncmp(env_var, "RANDOM_DELAY", 12) == 0) {
    280             r = match_rx("^([[:digit:]]+)$", value, 0);
    281             if (r != -1) {
    282                 int i = random();
    283                 double x = 0;
    284                 x = (double) i / (double) RAND_MAX * (double) (atoi(value));
    285                 random_number = (int)x;    ※ここで小数点以下切捨てだからvalueは含まない?
    286                 Debug(("Randomized delay set: %d", random_number));
    287             }
    288         else goto reg_invalid;
    289         }
"anacron/readtab.c"
これを見ても、生成される random_number の範囲に value が含まれるのか否か、頭の中だけでは判然とせず。手間ですが、実験プログラムを一筆書いてみました。
/*
        test_random.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>

get_random_number(char *value)
{
        int random_number;

        // next 4 lines are copied from anacron/readtab.c:parse_tab_line()
        int i = random();
        double x = 0;
        x = (double) i / (double) RAND_MAX * (double) (atoi(value));
        random_number = (int)x;

        return random_number;
}

main(int argc, char* argv[])
{
        int i ;
        int random_number ;
        struct timeval tv ;
        struct timezone tz ;

        if (argc <= 1) exit(1) ;

        gettimeofday(&tv, &tz) ;
        // cronie uses this method
        srandom(getpid()+tv.tv_usec) ;

        for (i = 0; i < 10000; i++) {
                random_number = get_random_number(argv[1]) ;
                printf("%d\n", random_number) ;
        }
}
# gcc -o test_random test_random.c 
# ./test_random 10 | sort -n | uniq -c
    993 0
   1028 1
   1006 2
   1011 3
    998 4
   1030 5
    999 6
    966 7
    985 8
    984 9
# ./test_random 45 | sort -n | uniq -c | tail 
    210 35
    207 36
    218 37
    250 38
    197 39
    221 40
    217 41
    217 42
    209 43
    233 44
というわけで、0 ≦ random_number < value ですね。

2014-05-05追記
RHEL7.0 RC を試しましたが、RHEL6/CentOS6 と同様で、もし cron.daily 実行時刻を固定化したい場合は、cronie-noanacron と入れ替えれば良いようです。デフォルトの /etc/anacrontab の設定にも変更は無いようです。

2014-07-21追記
いちいち書くまでもないと思いつつ、RHEL7/CentOS7 でも同様です。

2019-05-26追記
CentOS8 は、現在のところ準備中のようです。
https://wiki.centos.org/About/Building_8
確認したところ RHEL8 でも、cronie-noanacron は存在しており、ここに書いた手順が通用するようです。

2012年12月10日月曜日

3TB ディスクから CentOS 6.3 をブート

バックアップ用に 3TB のディスク (WD30EZRX/K) を購入しました。

まずは、Windows 7 で採取した CrystalDiskInfo の結果です。
ZALMAN ZM-HE350 U3E というケースに格納し、ThinkPad T510 に eSATA 接続しています。WD30EZRX/K は NCQ に対応していますが、このケース経由だと NCQ が使えません (他のドライブでも確認・経験済み) 。その点はちょっと残念。

さて、CentOS 6.3 ならば、UEFI 非対応のマシン (ThinkPad T510 も勿論非対応) でも、3TB ディスクからブート可能という情報がありましたので、実際にやってみました。他のドライブが繋がっているとヤヤコシイので、一旦 3TB ディスク以外は外してインストールしました。その後に、内臓 SSD などを戻しています。また、ThinkPad の BIOS でブートオーダーを変更して起動しました。
# parted -s /dev/sdc print
Model: ATA WDC WD30EZRX-00D (scsi)
Disk /dev/sdc: 3001GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number  Start   End     Size    File system     Name                  Flags
 1      1049kB  211MB   210MB   ext4                                  boot
 2      211MB   21.2GB  21.0GB  ext4
 3      21.2GB  23.3GB  2097MB  linux-swap(v1)
 4      23.3GB  3001GB  2977GB  ntfs            Basic data partition

# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/sdc2             20158332   4737476  14396856  25% /
tmpfs                  3986236       260   3985976   1% /dev/shm
/dev/sdc1               198337     51449    136648  28% /boot

# ls -l /dev/root
lrwxrwxrwx. 1 root root 4 Dec  9 22:10 /dev/root -> sdc2

# uname -a
Linux xxxx 2.6.32-279.14.1.el6.i686 #1 SMP Tue Nov 6 21:05:14 UTC 2012 i686 i686 i386 GNU/Linux
このように、うまく動作しました。
Fedora 16 以降なら、grub2 を使って GPT ラベルを付与したディスクからブート可能とは知ってましたが、grub1 でも対応パッチがあるようで、CentOS 6.3 の grub に取り込まれていたようです。
人気ブログランキングへ にほんブログ村 IT技術ブログへ