こんな経験はありませんか?ディスクの読み書き帯域は有限で、バックアップや
rsyncなどのバッチ処理が全力で走ると、Webサーバーやデータベースの応答に影響が出ることがあります。この問題を解決するのが
ionice コマンドです。Linuxにはプロセスごとに「I/O(ディスク読み書き)の優先度」を制御する仕組みがあり、ioniceを使えば「このバックアップ処理は空き時間だけ使う」「このDBプロセスは優先的にディスクを使えるようにする」といった制御ができます。この記事では、ioniceコマンドの3つのスケジューリングクラスの意味、実務でよく使うrsync・cron・systemdサービスへの適用方法、そして「設定したのに効かない」ときの原因と対処法まで解説します。
動作確認環境: RHEL 9.4 / Rocky Linux 9.4 / Ubuntu 24.04 LTS
この記事のポイント
・ionice -c 3 でアイドルクラス(空き時間のみ実行)に設定できる
・-p PID で実行中プロセスのI/O優先度をリアルタイムに変更できる
・systemdサービスに IOSchedulingClass=idle を設定する方法が最も確実
・NVMe SSD(noneスケジューラー)では ionice が無効になる場合がある
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
ioniceとは?I/O優先度を制御してサービスへの影響を防ぐ
Linuxのカーネルには「I/Oスケジューラー」が組み込まれており、複数のプロセスが同時にディスクにアクセスしようとした場合にどの順番で処理するかを決めます。ionice コマンドは、このI/Oスケジューラーに対して「このプロセスのディスクアクセスは低い優先度で扱ってほしい」と指定するためのツールです。設定できるスケジューリングクラスは以下の3種類です。
| クラス番号 | クラス名 | 動作 | 用途 |
|---|---|---|---|
| 1 | real-time(リアルタイム) | 他のプロセスより必ず先に処理される | 絶対に遅延させたくない処理(root権限必要) |
| 2 | best-effort(ベストエフォート) | プロセスのnice値に準じた優先度 | デフォルト。一般的なプロセス |
| 3 | idle(アイドル) | 他にI/Oがない時だけ実行される | バックアップ・インデックス更新など低優先度処理 |
ioniceの基本的な使い方
1. 実行中プロセスのI/O優先度を確認する
ionice -p PID でそのプロセスに設定されているI/O優先度を確認できます。# バックアップスクリプトのPIDを確認 pgrep -a rsync # I/O優先度を確認(PIDが1234の場合) ionice -p 1234
$ ionice -p 1234 none: prio 0 $ ionice -c 3 -p 1234 $ ionice -p 1234 idle: prio 7
2. コマンドにioniceを適用して実行する
コマンドの前にionice -c 3 を付けるだけです。# rsyncをidleクラスで実行(最もよく使うパターン) ionice -c 3 rsync -avz /home/ /backup/home/ # tarバックアップをidleクラスで実行 ionice -c 3 tar -czf /backup/etc-$(date +%Y%m%d).tar.gz /etc/ # best-effortで優先度を7(最低)に設定して実行 ionice -c 2 -n 7 find / -name "*.log" -mtime +30 -delete
-n オプションはbest-effortクラス(-c 2)またはreal-timeクラス(-c 1)の場合のみ意味を持ちます。値は0(高優先度)から7(低優先度)で指定します。idleクラス(-c 3)には優先度レベルがないため、-nは無視されます。3. 実行中のプロセスにI/O優先度を適用する(-pオプション)
すでに実行中のプロセスに対してもリアルタイムで変更できます。バックグラウンドで暴走しているプロセスへの即時対処に使えます。# 実行中のrsync(PID:1234)をidleクラスに変更 ionice -c 3 -p 1234 # pgrep でPIDを取得して一括変更 for pid in $(pgrep rsync); do ionice -c 3 -p "$pid" done # 変更を確認 ionice -p 1234
実務でよく使うioniceの適用パターン
1. cronジョブにioniceを組み込む
定期実行するバックアップスクリプトにioniceを付けるシンプルな方法です。# crontab -e で以下のように設定する # 毎日午前2時に、idleクラスでバックアップを実行 0 2 * * * ionice -c 3 /usr/local/bin/backup.sh
rsync や tar を複数呼ぶ場合も、個別にioniceを付け直す必要はありません。2. シェルスクリプトの先頭でI/O優先度を自分自身に設定する
既存のバックアップスクリプトを修正する場合、スクリプト内から自身のI/O優先度を変更できます。#!/bin/bash # スクリプトの先頭で自身をidleクラスに変更 ionice -c 3 -p $$ echo "バックアップ開始: $(date)" rsync -avz /home/ /mnt/backup/home/ --delete tar -czf /mnt/backup/etc-$(date +%Y%m%d).tar.gz /etc/ echo "バックアップ完了: $(date)"
$$ はシェルスクリプト自身のPIDです。先頭に1行追加するだけで、以降の全I/Oがidleクラスになります。3. systemdサービスにI/O優先度を設定する(最も確実な方法)
systemdで管理するサービスには、UnitファイルにIOSchedulingClass を設定するのが最も確実です。cronよりも設定が明示的で、管理しやすくなります。# /etc/systemd/system/backup.service [Unit] Description=Daily backup service After=network.target [Service] Type=oneshot ExecStart=/usr/local/bin/backup.sh # I/O優先度をidleクラスに設定 IOSchedulingClass=idle # CPU優先度も下げる場合(任意) Nice=19 [Install] WantedBy=multi-user.target
# systemdタイマーで定期実行する場合 # /etc/systemd/system/backup.timer [Unit] Description=Run backup daily at 02:00 [Timer] OnCalendar=02:00 Persistent=true [Install] WantedBy=timers.target
# サービスとタイマーを有効化 sudo systemctl daemon-reload sudo systemctl enable --now backup.timer # タイマーの状態確認 sudo systemctl list-timers backup.timer
IOSchedulingClass=idle を設定するとサービスとその子プロセス全体に適用されます。tar コマンドの実用例と組み合わせて、バックアップ処理全体を低優先度で実行する構成が作れます。ioniceが効かない時のトラブルシュート|原因と対処法
1. I/OスケジューラーがNVMe(none)の場合
最もよくある「効かない」原因です。 NVMe SSDなど高速ストレージを搭載したサーバーでは、I/Oスケジューラーがnone(スケジューリングなし)に設定されていることがあります。この場合、ioniceはI/Oスケジューラーに影響を与えません。# 現在のI/Oスケジューラーを確認(sdaの場合) cat /sys/block/sda/queue/scheduler # NVMe SSDの場合の出力例(noneが選択されている) [none] mq-deadline kyber bfq # HDDや一般的なSATASSDの場合の出力例 mq-deadline [bfq] none
[none] と表示されている場合、bfq(Budget Fair Queueing)スケジューラーへの変更を検討します。# sda を bfq スケジューラーに一時変更(再起動で元に戻る) echo bfq | sudo tee /sys/block/sda/queue/scheduler # 変更確認 cat /sys/block/sda/queue/scheduler # 期待される出力 mq-deadline [bfq] none
/etc/udev/rules.d/ にudevルールを追加します。# /etc/udev/rules.d/60-io-scheduler.rules として保存 ACTION=="add|change", KERNEL=="sd[a-z]*", ATTR{queue/scheduler}="bfq" ACTION=="add|change", KERNEL=="nvme[0-9]*", ATTR{queue/scheduler}="bfq" # udevルールを再読み込み sudo udevadm control --reload-rules sudo udevadm trigger
2. real-timeクラスで「Operation not permitted」が出る
real-timeクラス(-c 1)の設定はroot権限が必要です。# 一般ユーザーでreal-timeを設定しようとするとエラー $ ionice -c 1 -p 1234 ionice: cannot set I/O priority: Operation not permitted # sudo を付けて実行する sudo ionice -c 1 -p 1234
3. idleクラスなのにI/O負荷が下がらない
ioniceはプロセスのI/O優先度を制御しますが、I/O帯域幅そのものを制限するわけではありません。他にI/Oがなければidleクラスでも全帯域を使います。I/O帯域幅を上限設定するにはcgroupsのblkio(v1)または io(v2)コントローラーを使う必要があります。どのプロセスがI/Oを多く使っているかを特定するには
iotop や iostat が有効です。Linux ポート確認の全コマンドでも解説している ss コマンドでソケット単位の状況確認と合わせて診断することで、I/O問題の全体像が見えてきます。# iotopでリアルタイムにI/O使用状況を確認(要インストール) sudo iotop -o # iostatでディスク全体のI/O状況を1秒間隔で5回表示 iostat -x 1 5
本記事のまとめ
| やりたいこと | コマンド |
|---|---|
| 新規コマンドをidleクラスで実行 | ionice -c 3 コマンド名 |
| 実行中プロセスのI/O優先度を確認 | ionice -p PID |
| 実行中プロセスをidleクラスに変更 | ionice -c 3 -p PID |
| best-effortで最低優先度に設定して実行 | ionice -c 2 -n 7 コマンド名 |
| cronジョブをidleクラスで実行 | ionice -c 3 /path/to/script.sh |
| systemdサービスのI/O優先度を設定 | IOSchedulingClass=idle(Unitファイルに追記) |
| I/Oスケジューラーを確認 | cat /sys/block/sda/queue/scheduler |
| I/Oスケジューラーをbfqに変更 | echo bfq | sudo tee /sys/block/sda/queue/scheduler |
ionice -c 3 の1行を追加するだけで防げることが多いので、今すぐcronやシェルスクリプトに組み込んでみてください。systemdのサービス設定全般については、systemd-analyze で起動時間計測も合わせて読むと、systemdの全体像の理解が深まります。
Linux無料マニュアルを受け取る >>
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:pmapコマンドでLinuxプロセスのメモリマップを確認する方法|メモリリーク調査とOOM対策の実践手順
- この記事の属するカテゴリ:Linuxtipsへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます