- 投稿日:2019-03-01T20:42:33+09:00
Linux PC内のパケット経路を確認するならip route getで
はじめに
Linuxでルーティングを確認する際によく使うのはtracert, tracepathだと思います。
が、実際に知りたい経路ってPC内の外に出るまでの経路が知りたい場合の方が個人的には多いんですよね。
ググっていつも引っかかるのはtracert,tracepathだったりしますが、こちらはPCから抜けた先がメインなのでちょっと違う。そんな時用のコマンド、以前に一時期使ってから忘れてしまって困ってたんですが、今日再び発見したので覚書
自PC内のルーティングが知りたい、そんな時には
ip route get使っていたコマンドはこれです。
ip route get IPアドレス。
こんな感じでどのデバイス・アドレス宛にルーティングが組まれているかが分かります。$ ip route get 192.168.1.233 192.168.1.233 dev br0 src 192.168.1.1Androidのように細かなルーティングを組んでるシステムだと便利
Android OS上のルーティングって、ip routeのルーティングだけじゃなくip ruleを組み合わせた構成になっています。
通常は意識しないからいいけど、ここに自前でローカルネットワークを追加しようとなるとすぐ「あれ?この場合はどこに抜けるんだ?」みたいになりがち。
tracertでも追えなくはないけどnetwork unreachableになると追いにくかったりしたので、単純に「このIPはどこに抜けるのか?」が分かるこのコマンドが非常に便利でした。
- 投稿日:2019-03-01T18:51:06+09:00
Raspberry Piでfstab弄ったら起動できなくなった場合の備忘録
外付けのHDDを繋げて、fstab弄って再起動・・・
あれ?SSH繋がんなくなった・・・。しばらく経っててログインできるはずなのに。と思ってHDMIケーブルを繋いで起動チェックしたところ、Emergency Modeに入っていました。Enterキー押してもうまく動かなかった。
ぐぐってたらこんな記事を発見。
https://www.rocher.kyoto.jp/arbr/?p=1378
早速これを基に作業を実施。
SDカードを別Linuxマシンにマウント
肝心のデータファイルはext系(多分ext4)のフォーマットなので、Windowsマシンでは認識してくれません。ですので仮想マシンとかでいいのでLinuxを使用します。私はサブマシンがUbuntuだったのでそちらを使用しました。
Ubuntu Desktopでは基本的に自動マウントしてくれますので、ファイルブラウザに載っています。
名前はrootfsっていう名前のはずです。fstabを弄る
rootfs内は至って普通のLinuxディレクトリ形式なので、
etc/fstabを弄くります。sudo使って編集しなければいけません。今回は簡単にoptionsにnofailと付けて保存。
ちなみにoptionsのnofailはマウントに失敗しても起動してくれるオプションです。
外付け系のハードディスクは基本的にこれを使ったほうが安心です。特にヘッドレスセットアップしているときはnofailを付けるべきです。今回の私のようになってしまいます。
起動
あとはそれをラズパイに戻すだけ。きっと起動するはずです。
- 投稿日:2019-03-01T17:46:00+09:00
swap領域を使っているプロセスを表示する。
swap領域を使っているプロセス5件を調べるワンライナーを作ってみました。かなり強引ですが。。。
# echo "==== swap ====" ; grep VmSwap /proc/*/status | sort -k 2 -t ":" -r | head -5 ; echo "==== ps ====" ; grep VmSwap /proc/*/status | sort -k 2 -t ":" -r | head -5 | awk -F'[/]' '{print $3}' | xargs ps -p実行例を載せておきます。
# echo "==== swap ====" ; grep VmSwap /proc/*/status | sort -k 2 -t ":" -r | head -5 ; echo "==== ps ====" ; grep VmSwap /proc/*/status | sort -k 2 -t ":" -r | head -5 | awk -F'[/]' '{print $3}' | xargs ps -p ==== swap ==== /proc/42790/status:VmSwap: 193052 kB /proc/107858/status:VmSwap: 25364 kB /proc/774/status:VmSwap: 12484 kB /proc/108833/status:VmSwap: 10604 kB /proc/109552/status:VmSwap: 6364 kB ==== ps ==== PID TTY STAT TIME COMMAND 774 ? S 0:00 /sbin/dhclient -d -q -sf /usr/libexec/nm-dhcp-helper -pf /var/run/dhclient-ens160.pid -lf /var/lib/NetworkManager/dhclient-b79ef9d4-5822-4 42790 ? Sl 115:54 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid 107858 ? Ssl 0:14 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid 108833 ? Ssl 12:22 /usr/bin/python2 -Es /usr/sbin/tuned -l -P 109552 ? Ss 4:57 /usr/sbin/httpd -DFOREGROUND
- 投稿日:2019-03-01T17:42:06+09:00
GRUB設定でコンソール画面を古いVGAモニターの解像度に変更
背景
仮想ではない物理的なベアメタルサーバーにubuntu serverをインストールした際に、古いVGA解像度のモニターしかデータセンター内に無くて、インストール後のサーバーのコンソール画面が表示されずに困った際のメモ。
表示モニター
古いスクエアタイプのモニターのVGA解像度でXGA(1024x768)です。
サーバー機器の場合はHDMIやDPじゃなくてVGA端子出力が割と多い。OS
「ubuntu server 16.04 LTS」でGRUB2自体はXGA(1024x768)の解像度で表示されます。
OSのubunruが起動後のCLI画面はSXGA(1280x1024)で設定されているので、インストール後の画面が対応モニターで無い場合は表示されない状態になります。OS起動前のGRUB2画面での設定
OS起動前のGRUB2画面で「e」のキーを押して編集モードを表示します。
以下の箇所を編集します。変更前gfxmode $linux_gfx_mode変更後gfxmode 1024x768その他にlinux行の末尾にオプションを追加します。
linux行の末尾へ追加nomodeset編集が出来たら、「F10」キーを押してそのまま起動を継続します。
これで古いVGAモニターのXGA(1024x768)解像度でもコンソール画面が表示されます。GRUB2の設定保存
このままだと再起動時には元に戻って変わらないので、GRUB2設定を保存します。
/etc/default/grubGRUB_CMDLINE_LINUX_DEFAULT="nomodeset" GRUB_CMDLINE_LINUX="video=1024x768"設定内容をGRUB2へ反映させます。
設定コマンドを実行$ sudo grub-mkconfig -o /boot/grub/grub.cfgこれで再起動時にも変更したVGAモニターの解像度になります。
- 投稿日:2019-03-01T15:53:18+09:00
【読解入門】Linuxカーネル (スケジューラ編その3-1)
各スケジューリングクラス
前回、下記クラスの概要について述べました。徐々に核心部分に近づいていきます。今回は各クラスをもう少し掘り下げてみていきたいと思います。
1.STOPクラス
2.DEADLINEクラス
3.RTクラス
4.FAIRクラス
5.IDLEクラス本内容は量が多いため、1を「その3-1」、2~3を「その3-2」、4~5を「その3-3」と分割して述べていきます。
sched_class構造体
各クラスのスケジューリング アルゴリズムの前に非常に重要な構造体を説明します。sched_class構造体です。本構造体は各クラスごとに定義し、スケジューラ コアからは本構造体のメンバ経由で呼び出されます。
本構造体は基本的には関数ポインタのメンバで構成されていて、スケジューラ コアからは関数ポインタで呼び出されます。
下記に構造体の定義と各メンバで何をするのかコメントで記載していきます。
なお、コードを読解しやすくするためにUPシステムを想定して述べます。(CONFIG_SMPで囲まれている箇所は割愛)kernel/sched/sched.hstruct sched_class { const struct sched_class *next; //次の優先度のスケジューリング クラスを指す。優先度は本ページの先頭に記載した1~5の順 void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags); //引数で指定したプロセスを実行キューに繋ぐ処理を定義 void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags); //引数で指定したプロセスを実行キューから外す処理を定義 void (*yield_task) (struct rq *rq); //currentプロセスが実行権を明渡す時の処理を定義 bool (*yield_to_task)(struct rq *rq, struct task_struct *p, bool preempt); //指定したプロセスにCPU実行権を渡す処理。fairクラスでのみ使用する void (*check_preempt_curr)(struct rq *rq, struct task_struct *p, int flags); //実行可能状態のプロセスが現在実行しているプロセスをプリエンプトすべきかチェックする処理 /* * It is the responsibility of the pick_next_task() method that will * return the next task to call put_prev_task() on the @prev task or * something equivalent. * * May return RETRY_TASK when it finds a higher prio class has runnable * tasks. */ struct task_struct * (*pick_next_task)(struct rq *rq, struct task_struct *prev, struct rq_flags *rf); //次に実行するプロセスを決定して、そのプロセスを示す構造体(task_struct)を返す処理を定義 void (*put_prev_task)(struct rq *rq, struct task_struct *p); //CPUの実行権を明渡したプロセスを引数で指定して呼び出す処理を定義 void (*set_curr_task)(struct rq *rq); //スケジューリングクラスを変更する時に実施する処理を定義 void (*task_tick)(struct rq *rq, struct task_struct *p, int queued); //タイマー割込みから呼び出される処理を定義 void (*task_fork)(struct task_struct *p); //プロセス生成時の処理を定義 void (*task_dead)(struct task_struct *p); //プロセス終了時の処理を定義 /* * The switched_from() call is allowed to drop rq->lock, therefore we * cannot assume the switched_from/switched_to pair is serliazed by * rq->lock. They are however serialized by p->pi_lock. */ void (*switched_from)(struct rq *this_rq, struct task_struct *task); //スケジューリングクラスを変更する時の処理を定義 void (*switched_to) (struct rq *this_rq, struct task_struct *task); //スケジューリングクラスを変更する時の処理を定義 void (*prio_changed) (struct rq *this_rq, struct task_struct *task, int oldprio); //プロセスの優先度が変更された時に実施する処理を定義 unsigned int (*get_rr_interval)(struct rq *rq, struct task_struct *task); //ラウンドロビン型プロセスのラウンドロビンするタイムスライスを返す処理を定義。 void (*update_curr)(struct rq *rq); //現在のプロセスの統計情報を取得する処理を定義 #define TASK_SET_GROUP 0 #define TASK_MOVE_GROUP 1 #ifdef CONFIG_FAIR_GROUP_SCHED void (*task_change_group)(struct task_struct *p, int type); //グループを変更した時に行う処理を実施 #endif };これらのメンバーの中で2点ほど補足します。
(1)スケジューリング クラスの変更
本記事を読まれている方は「各プロセスのスケジューリング クラスは一度設定すれば、その後は変更することはほとんどないんじゃないの?」と思われると思います。
実はユーザーの見えないカーネル内部ではスケジューリング クラスの変更が頻繁に行われています。最たる例は、優先度継承です。優先度継承の詳細はZephyr入門(排他制御:mutex編)を参照してください。
例えば、高優先度プロセスAがRTクラス、低優先度プロセスBが一般クラスの時、低優先度プロセスBが保持しているmutexを高優先度プロセスAが取得しようとすると優先度継承が行われます。
この時、低優先度プロセスBが高優先度Aの優先度までブーストされる為、一般クラスからRTクラスにクラス変更されます。そして、優先度継承の終了時はRTクラスから元の一般クラスに戻ります。(2)グループの変更
cgroupという言葉を聞いた事はありますか?
各プロセス群をグルーピングしてそれぞれのグループに対して使用できる資源を割り当てる機能のことです。
以前カーネルドキュメントにあった例だと、教師グループ、生徒グループを定義して全員をいずれかのグループに設定します。
コアが4つある場合、1つを教師グループ、3つを生徒グループに割当てることで生徒グループのコア群が高負荷になっても教師グループの先生は割り当てられている1コアを使用でき、コマンドレスポンス/GUIが遅いという事を防げます。
グループの変更と言うのは生徒グループから教師グループに変更、といったことを指しています。rq構造体
sched_class構造体以外にもう一つ重要な構造体があります。
本構造体はCPUごとに存在します。
sched_class構造体は各スケジューリング クラスの処理を定義しているのに対してrq構造体(以後、ランキューと述べます)はスケジューラを正常に動作させる為の構造体と思っていただいて構いません。本構造体のメンバはここでは説明せずに後述する説明で出てきたときに述べたいと思います。kernel/sched/sched.h/* * This is the main, per-CPU runqueue data structure. * * Locking rule: those places that want to lock multiple runqueues * (such as the load balancing or the thread migration code), lock * acquire operations must be ordered by ascending &runqueue. */ struct rq { /* runqueue lock: */ raw_spinlock_t lock; /* * nr_running and cpu_load should be in the same cacheline because * remote CPUs use both these fields when doing load calculation. */ unsigned int nr_running; #define CPU_LOAD_IDX_MAX 5 unsigned long cpu_load[CPU_LOAD_IDX_MAX]; #ifdef CONFIG_NO_HZ_COMMON unsigned int nohz_tick_stopped; atomic_t nohz_flags; #endif /* CONFIG_NO_HZ_COMMON */ /* capture load from *all* tasks on this CPU: */ struct load_weight load; unsigned long nr_load_updates; u64 nr_switches; struct cfs_rq cfs; struct rt_rq rt; struct dl_rq dl; #ifdef CONFIG_FAIR_GROUP_SCHED /* list of leaf cfs_rq on this CPU: */ struct list_head leaf_cfs_rq_list; struct list_head *tmp_alone_branch; #endif /* CONFIG_FAIR_GROUP_SCHED */ /* * This is part of a global counter where only the total sum * over all CPUs matters. A task can increase this counter on * one CPU and if it got migrated afterwards it may decrease * it on another CPU. Always updated under the runqueue lock: */ unsigned long nr_uninterruptible; struct task_struct *curr; struct task_struct *idle; struct task_struct *stop; unsigned long next_balance; struct mm_struct *prev_mm; unsigned int clock_update_flags; u64 clock; u64 clock_task; atomic_t nr_iowait; #ifdef CONFIG_IRQ_TIME_ACCOUNTING u64 prev_irq_time; #endif #ifdef CONFIG_PARAVIRT u64 prev_steal_time; #endif #ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING u64 prev_steal_time_rq; #endif /* calc_load related fields */ unsigned long calc_load_update; long calc_load_active; #ifdef CONFIG_SCHED_HRTICK struct hrtimer hrtick_timer; #endif #ifdef CONFIG_SCHEDSTATS /* latency stats */ struct sched_info rq_sched_info; unsigned long long rq_cpu_time; /* could above be rq->cfs_rq.exec_clock + rq->rt_rq.rt_runtime ? */ /* sys_sched_yield() stats */ unsigned int yld_count; /* schedule() stats */ unsigned int sched_count; unsigned int sched_goidle; /* try_to_wake_up() stats */ unsigned int ttwu_count; unsigned int ttwu_local; #endif #ifdef CONFIG_SMP struct llist_head wake_list; #endif #ifdef CONFIG_CPU_IDLE /* Must be inspected within a rcu lock section */ struct cpuidle_state *idle_state; #endif };各クラスのsched_class構造体メンバの処理内容
1.STOPクラス
本クラスのsched_class構造体を以下に示します。
kernel/sched/stop_task.cconst struct sched_class stop_sched_class = { .next = &dl_sched_class, .enqueue_task = enqueue_task_stop, .dequeue_task = dequeue_task_stop, .yield_task = yield_task_stop, .check_preempt_curr = check_preempt_curr_stop, .pick_next_task = pick_next_task_stop, .put_prev_task = put_prev_task_stop, .set_curr_task = set_curr_task_stop, .task_tick = task_tick_stop, .get_rr_interval = get_rr_interval_stop, .prio_changed = prio_changed_stop, .switched_to = switched_to_stop, .update_curr = update_curr_stop, };・ nextメンバ
これは次の優先度のsched_class構造体を示します。
STOPクラスの次に優先度が高いDEADLINEクラスの構造体dl_sched_classを指しています。・enqueue_taskメンバ
kernel/sched/stop_task.cstatic void enqueue_task_stop(struct rq *rq, struct task_struct *p, int flags) { add_nr_running(rq, 1); }本関数はCPU毎に保持しているランキューのnr_runningメンバをインクリメントしています。
nr_runningメンバは実行可能状態のプロセス数を保持します。・dequeue_taskメンバ
kernel/sched/stop_task.cstatic void dequeue_task_stop(struct rq *rq, struct task_struct *p, int flags) { sub_nr_running(rq, 1); }本関数はenqueue_taskメンバの逆です。ランキューの実行可能プロセス数nr_runningメンバをデクリメントします。
・yield_taskメンバ
kernel/sched/stop_task.cstatic void yield_task_stop(struct rq *rq) { BUG(); /* the stop task should never yield, its pointless. */ }STOPクラスのプロセスはCPU実行権を自ら手放すことを許しません。
処理を最後まで完遂させる必要があります。
従って、本関数が呼ばれるとBUG( ) (警告:カーネル バグ)でコンソールに警告を出力します。・check_preempt_currメンバ
kernel/sched/stop_task.cstatic void check_preempt_curr_stop(struct rq *rq, struct task_struct *p, int flags) { /* we're never preempted */ }stopクラスは最高優先度のためプリエンプションされません。この為、空関数になっています。
なお、プリエンプションというのは「高優先度プロセスが実行可能となった時に低優先度プロセスからCPUの実行権を奪って処理を行うこと」です。下図を参考ください。
・pick_next_taskメンバ
kernel/sched/stop_task.cstatic struct task_struct * pick_next_task_stop(struct rq *rq, struct task_struct *prev, struct rq_flags *rf) { 1 struct task_struct *stop = rq->stop; 2 if (!stop || !task_on_rq_queued(stop)) 3 return NULL; 4 put_prev_task(rq, prev); 5 stop->se.exec_start = rq_clock_task(rq); 6 return stop; }1行目で、ランキューのstopメンバを取り出して、stopクラスのメンバーが存在しない場合はNULLを返します(2行目、3行目)
4行目は以下の通り、stopクラスのput_prev_taskメンバを呼び出します。
kernel/sched/sched.hstatic inline void put_prev_task(struct rq *rq, struct task_struct *prev) { prev->sched_class->put_prev_task(rq, prev); }kernel/sched/stop_task.cstatic void put_prev_task_stop(struct rq *rq, struct task_struct *prev) { 1 struct task_struct *curr = rq->curr; 2 u64 delta_exec; 3 delta_exec = rq_clock_task(rq) - curr->se.exec_start; 4 if (unlikely((s64)delta_exec < 0)) 5 delta_exec = 0; 6 schedstat_set(curr->se.statistics.exec_max, 7 max(curr->se.statistics.exec_max, delta_exec)); 8 curr->se.sum_exec_runtime += delta_exec; 9 account_group_exec_runtime(curr, delta_exec); 10 curr->se.exec_start = rq_clock_task(rq); 11 cgroup_account_cputime(curr, delta_exec); }3行目で現在のプロセスの実行時間を求めます。(現在の時間 - 現在のプロセスの開始時間)
4、5行目は実行時間が負の場合、delta_execに0を入れます。
6、7行目は統計情報を設定しています。これは/proc/schedstatでユーザー空間に見せます。8、9行目で現在のプロセスの実行時間を加算しています。
10行目で現在のプロセスの開始時間を現時点の時間に設定します。
11行目はcgroupの使用帯域の元になるCPU実行時間を加算しています。端的に述べると、本関数の肝は1行目のランキューのstopで設定されているプロセスを返すということです。
・put_prev_taskメンバ
本メンバの説明はpick_next_taskメンバの中で説明したため、割愛します。・set_curr_taskメンバ
kernel/sched/stop_task.cstatic void set_curr_task_stop(struct rq *rq) { 1 struct task_struct *stop = rq->stop; 2 stop->se.exec_start = rq_clock_task(rq); }1行目でランキューのstopメンバをstopに設定します。
2行目で現在の時間をstopのexec_startに設定します。・task_tickメンバ
kernel/sched/stop_task.cstatic void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued) { }stopクラスでは空関数です。
・get_rr_intervalメンバ
kernel/sched/stop_task.cstatic unsigned int get_rr_interval_stop(struct rq *rq, struct task_struct *task) { return 0; }0を返します。
・prio_changedメンバ
kernel/sched/stop_task.cstatic void prio_changed_stop(struct rq *rq, struct task_struct *p, int oldprio) { BUG(); /* how!?, what priority? */ }stopクラスでは優先度という概念は存在しないため、本関数が呼ばれたらBUG( )で警告を出力します。
・switched_toメンバ
kernel/sched/stop_task.cstatic void switched_to_stop(struct rq *rq, struct task_struct *p) { BUG(); /* its impossible to change to this class */ }stopクラスでプロセス スイッチすることはできないため、本関数が呼ばれたらBUG( )で警告を出力します。
・update_currメンバ
kernel/sched/stop_task.cstatic void update_curr_stop(struct rq *rq) { }空関数です。
以上で、stopクラスの各関数を一通り見ました。(文字にすると長い…。)
次回はdeadlineクラスとrtクラスを見ます。
なお、スケジューラを理解するにあたって、rtクラスとfair(一般)クラスを理解することが肝だと考えています。その後、コア部を読解することでコア部と各クラスの処理内容が結びつき、スケジューラをざっくり理解していただければ、と思います。
- 投稿日:2019-03-01T15:43:07+09:00
特定のディレクトリ配下のファイルを容量の大きい順に表示する。(MB表示)
# ls -la --block-size=MB $(find "ディレクトリ名" -type f) | sort -nr -k5 | head例)「/var/log」の場合
# ls -la --block-size=MB $(find /var/log/ -type f) | sort -nr -k5 | head -rw------- 1 root utmp 46MB 3月 1 06:43 /var/log/btmp-20190301 -rw------- 1 root root 16MB 2月 17 07:52 /var/log/secure-20190217 -rw-r--r-- 1 mysql mysql 14MB 3月 1 14:28 /var/log/mysqld.log -rw------- 1 root root 13MB 2月 24 08:28 /var/log/secure-20190224 -rw------- 1 root root 13MB 2月 3 06:06 /var/log/secure-20190203 -rw------- 1 root root 11MB 2月 17 07:52 /var/log/fail2ban.log-20190217 -rw------- 1 root root 11MB 2月 3 06:05 /var/log/maillog-20190203 -rw------- 1 root root 10MB 2月 17 07:51 /var/log/maillog-20190217 -rw------- 1 root root 10MB 2月 10 03:48 /var/log/maillog-20190210 -rw------- 1 root root 9MB 2月 24 08:28 /var/log/maillog-20190224
- 投稿日:2019-03-01T15:38:48+09:00
RHEL DVD iso を使用した yum リポジトリの設定
参考URL
https://access.redhat.com/ja/solutions/117643
ISO イメージでリポジトリーを作成する
ISO イメージをマウント
サーバの適当なディレクトリにISOイメージを配置し、マウントする
mkdir -p /mnt/rhiso mount -o loop RHELX-XXXX.iso /mnt/rhisorepoファイルの作成
/etc/yum.repos.d ディレクトリにリポジトリファイルを作成する。
vi /etc/yum.repos.d/dvd.repo [RHEL5-Server-DVD] name=Red Hat Enterprise Linux $releasever - $basearch (DVD) baseurl=file:///mnt/rhiso/Server enabled=1 gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-releaseyum install
以下のコマンドでインストールする
yum --disablerepo=* --enablerepo=RHEL5-Server-DVD install [package name]
- 投稿日:2019-03-01T15:30:30+09:00
isoファイルをマウントする
- 投稿日:2019-03-01T00:11:54+09:00
Linuxコマンド備忘録
Linuxコマンドを自分用備忘録を記述していきます
SESになって現場経験半年で覚えたコマンドをただただ自分用に書き出していきます。
lsコマンド
$ ls index.html main.css index.rb main.js dir1ディレクトリの中身を一覧表示してくれる
オプション
-l : パーミッションも一緒に表示してくれる
-1 : 縦に一覧表示してくれるtailコマンド
$ tail ファイル名 #ファイルの最後から数行を表示してくる num = 1 for num in 1..100 print num print " " puts " " if num % 10 == 0 num += 1オプション
-f : ファイルが更新されたら、その更新も出力してくれる。ログの監視に便利!最後に
半年でこれだけかって思うかもしれませんが、初投稿だからテストがてらあげてみました。
これからちょくちょくあげていければいいな〜と思っている今日このごろです。
