見出し画像

【マイグレーションTips】RHEL8にバージョンアップ後、OSコマンドが性能劣化した?!件


はじめに


皆さん、こんにちは。株式会社SHIFT アプリケーションサービスGの村田です。
主にお客様が使用するコンピュータシステムのマイグレーション作業支援を担当しています。

マイグレーションTipsと題して、マイグレーション作業を行う技術者に向けて役に立つと考えられる情報を選んで紹介しています。

※「マイグレーションって何?」と思われた方は、以下の記事で説明していますので先にお読み頂けると嬉しいです。

【現象】RedHat LinuxをRHEL8にバージョンアップしたら、シェルスクリプトの実行時間が4倍以上かかった!


今回紹介する事例は、OSバージョンアップに伴ってシェルスクリプトを移植する時に遭遇した問題への解決方法です。

  • システム:RedHat Linuxのバージョンアップ(RHEL6.5→RHEL8.2)

  • 言語:シェル(mksh)

  • 事象:RHEL6.5で稼働中のシステムをRHEL8.2に刷新。
    RHEL6.5で稼働中のシェルスクリプトをRHEL8.2の環境に移植したら、RHEL8.2では実行時間が4.2倍に延びた

OSバージョンアップに伴ってシェルスクリプトを移植する時に遭遇した問題(筆者作成)

マイグレーション作業では、OSやDBMSのバージョンアップに対応するためにまず新旧の仕様差異を調べます。そして仕様差異に影響を受けるプログラムやシェルスクリプトがあれば必要な改修を行ってから動作確認するという流れを取ります。

もちろん今回もこれらの作業は実施済みでしたが、仕様差異の影響はないと判断していたシェルスクリプトで問題が起きました。

何が起きたのか、簡単なサンプルコードで説明しましょう。

-- sample.sh --

#!/bin/mksh
# 初期設定

INFILE1=fileA
INFILE2=fileB
INFILE3=fileC
OUTFILE=fileZ

# ファイル結合
date
cat $INFILE1 $INFILE2 $INFILE3 > $OUTFILE
date

exit 0

問題が起きたシェルスクリプトのコードです。
シェルスクリプトを起動すると、3つのファイルを連結して1つのファイルにまとめます。
シンプルなスクリプトなので、OSの仕様差異調査では問題なし。 しかしRHEL 6.5、RHEL 8.2それぞれでテストしてみたところ…

RHEL6.5、RHEL8.2での実行結果(筆者作成)

どちらもシェルスクリプトは正常終了するものの、RHEL8.2の方が明らかに時間がかかっていました。
RHEL6.5とRHEL8.2で実行したシェルスクリプトの内容は同じで、一見どこも悪いようには見えません。 RHEL8.2のサーバのCPU負荷が高かったのかも…と考えて、何度かトライしたものの結果は変わらず。

一体何が起きているのでしょうか。

【原因】OSバージョンアップにより、同名のコマンドがビルトインコマンドに追加された!


本件はシェルスクリプトで呼び出すcatコマンドがOSバージョンアップによって変わったことが原因でした。

<原因>
RHEL8.2のmkshにて、ビルトインコマンドとしてcatが追加された

RHEL6.5では、シェルスクリプトで「cat」を記述するとOSで標準装備されているcatコマンドを実行していましたが、RHEL8.2のmkshではmkshのビルトインコマンドcatを実行するように動作が変わっていました。

== RHEL6.5 catコマンド ==
RHEL6 $ echo $SHELL
/bin/mksh
RHEL6 $ type cat
cat is /bin/cat
RHEL6 $ 
== RHEL8.2 catコマンド ==
RHEL8 $ echo $SHELL
/usr/bin/mksh
RHEL8 $ type cat
cat is a shell builtin
RHEL8 $ 

同名であっても実際に動作するコマンドが変わったことで、性能劣化を起こしたように見えたことが判明しました。

詳しく説明しましょう。
RHEL6.5でのmkshのビルトインコマンドの説明の中には、catコマンドはありません。

RHEL6 $ man mksh
MKSH(1)

NAME
    mksh, sh -- MirBSD Korn Shell
~
    Additional mksh regular commands

    [ , bind, echo, let, mknod, print, pwd, realpath, rename,, test, ulimit, whence

    If the future, the additional mksh special and reqular commands may be treated differntly from the POSIX special and regular command.
    Once the type of command has been determined, ny command-line parameter assignments are performed and exported for the duration of the ocommand. 
~

しかしRHEL8.2でのmkshのビルトインコマンドの説明には、catコマンドが登場します。

RHEL8 $ man mksh
MKSH(1)

NAME
    mksh, sh -- MirBSD Korn Shell
~
    Builtins that are not special:
    ※訳(特別ではない組み込み)
    [, alias, bg, bind, cat, cd, command, echo, false, fc, fg, getopts, jobs,
    kill, let, mknod, print, pwd, read, realpath, rename, sleep, test, true, 
    ulimit, umask, unalias, whence
~
    cat [-u] [file ...]
       Read files sequetially, in command line order, and write them to standard output.
       It a file is a single dash(e-f) or absent, read from standard input. 
       Unless compiled with MKSH_NO_EXTERNAL_CAT, if any options are given, an external cat(1) utility is involed instead if called from the shell.
       For direct builtin calls, the POSIX -u option is supported as a  no-op.
~

もちろんRHEL8.2にもOS標準装備のcatコマンドは存在します。RHEL6.5時代と仕様差はありませんので、こちらが動作すればOSをバージョンアップしたとしても同じ動作を行います。

しかしシェルスクリプトに相対パスでコマンドを記載した場合、コマンドサーチパスの優先順位に従って実行するコマンドを探します。
コマンドサーチパスの優先順位は、ビルトインコマンドが最優先です。そのため環境変数PATHに記載したディレクトリに同一名称のコマンドがあった場合でも、RHEL8.2ではビルトインコマンドを実行するという形になりました。

もしビルトインコマンドcatがOS標準装備のcatコマンドと同等の性能であれば、何の問題もなく使っていたのでしょうが、ビルトインコマンドcatの性能が良くなかったことから性能劣化が発覚したことになります。

<参考>  
ちなみに性能劣化の調査中、以下の観点についての調査も行いました。

  • シェルスクリプトを介さずに、プロンプトからcatコマンドを直接実行
    ⇒ 性能劣化が発生した!
    ⇒ これって(OSの)catコマンドに問題ありなのか?

調査した結果、こちらも原因はビルトインコマンドcatの性能問題であることが判明しています。

①サーバにログインするユーザの標準シェルとしてmkshを適用している

== RHEL8.2 catコマンド ==
RHEL8 $ echo $SHELL
/usr/bin/mksh
RHEL8 $ type cat
cat is a shell builtin
RHEL8 $ 

②サーバにて、catコマンドを実行

RHEL8 $ cat fileA fileB fileC > fileZ
RHEL8 $ 
  • 相対パスでcatコマンドを実行

  • サーチパスの指示に基づき、OSコマンドのcatではなく、ビルトインコマンドcatが動作

  • 性能劣化が発生 

という流れでした。

【調査方法】topコマンドの実行結果から切り分けて判明!


今回の性能劣化の問題点を調査するにあたり、決め手になったのはtopコマンドの実行結果でした。

topコマンドとは、Linuxにおいて実行中のプロセスの情報をリアルタイムで表示してくれるコマンドです。

「top コマンドは CPU/メモリの利用状態を全体、および各プロセスごとに確認することができます。」

出典:SEの道標

https://milestone-of-se.nesuke.com/sv-basic/linux-basic/top-command/

topコマンドを実行するとCPUを多く消費しているプロセスがわかるため、プロセスの実行に時間がかかっている時のトラブルシュートに良く使われます。

今回の件もRHEL8.2の環境でtopコマンドを実行してみました。

RHEL8.2環境でのtopコマンド実行結果(筆者作成)

①topコマンドの結果から、kshがCPUを消費していることがわかりました。
②kshから子プロセスとしてOSのcatコマンドを呼び出している想定ですが、topでは出てきませんでした。
③kshのプロセスID(1763490)を親とする子プロセスの存在を探しましたが、存在しませんでした。

以上の結果から、改めてmkshのmanを確認した結果、ビルトインコマンドcatの存在が明らかになったという訳です。

【対策】catコマンドの記述を見直す


この問題の対策は、シェルスクリプト中のcatコマンドの記述を見直します。

  • [対策] OS標準装備のcatコマンドを明示的に実行する
    catコマンドを完全パスで指定して、OS標準装備のコマンドを動作させるようにします。

#	cat $INFILE1 $INFILE2 $INFILE3 > $OUTFILE         # 対策前 
/usr/bin/cat $INFILE1 $INFILE2 $INFILE3 > $OUTFILE  # 対策後 完全パス指定

簡単な対策ではありますが、catコマンドは便利なコマンドゆえに様々なシチュエーションで使われている可能性があります。対策漏れがないようにしっかりgrepする必要がありますね。

ちなみに上記対策を行って再実行した結果は…

$ sh sample.sh
2024-06-22 09:25;39
2024-06-22 09:28:06
$

1時間17分25秒かかっていたシェルスクリプトが、2分27秒で終了しました。 サーバの性能差もあるのですが、RHEL6時代よりもかなり早くなりました。

【関連事項】ビルトインコマンドのラインアップはシェル毎に異なる


Linuxではmksh以外にもシェルが存在します。実はシェルの種類によりビルトインコマンドのラインアップは異なります。

シェルの種類とcatコマンドの対応状況を以下に示します。

今回のマイグレーション対象システムではシェルとしてmkshを使っていたため、問題となりました。
前回ご紹介したsleepコマンドの事例 と同様に、ビルトインコマンドの名称はreadなどOS提供のコマンドと同じ名称のものが多く、今後のOSバージョンアップでも類似事例が発生する可能性があります。
新環境に移植したシェルスクリプトがエラーを検知した時は、シェルのビルトインコマンドが原因となっていないか、についても確認するようにして下さい。

最後に


マイグレーションTipsとして「RHEL8にバージョンアップ後、OSコマンドが性能劣化した?!件」をご紹介しましたが、いかがだったでしょうか。

Redhat Linuxは、古いバージョンのサービス提供終了(EOSL(End of Service Life))が迫ってきたこともあり、RHEL8やRHEL9へのバージョンアップに伴うマイグレーション案件が増えてきています。

マイグレーションに携わる技術者の皆さんに、この記事が目に留まり少しでも役立てて頂ければ幸いです。

マイグレーションTipsの記事一覧


執筆者プロフィール:村田 博之
IT業界に入って40年突破。データベース関連ミドルウェアの開発・保守(20年間)やメインフレームおよびオープン環境での社内システム開発・保守SE(合計19年間)に従事した後、SHIFTに⼊社。
現在は数々の案件対応で蓄積した知⾒と経験を活かして、マイグレーション関連のプロジェクトに参画している。
特種情報処理技術者、データベーススペシャリスト

マイグレーション支援サービスのご紹介

株式会社SHIFTでは、コンピュータシステムのマイグレーションを円滑に進めるための支援サービスを提供しています。
マイグレーションに関する支援サービスの詳細は以下のとおりです。
システムのマイグレーションをご検討、または課題解決に困っている方がいらっしゃったら、以下のページよりお気軽に問い合わせいただければ幸いです。

お問合せはお気軽に

SHIFTについて(コーポレートサイト)

SHIFTのサービスについて(サービスサイト)

SHIFTの導入事例

お役立ち資料はこちら

SHIFTの採用情報はこちら