20191126のLinuxに関する記事は16件です。

shell やlinuxでファイル名の特殊文字をエスケープしたい!

タイトルそのままlinuxコマンドで

問題

wc -l  /var/tmp/20191126-(2,135,397個)テストファイル.csv

のように「20191126-(2,135,397個)ファイル.csv」ファイルの行数を取得しようとしたらエラー

-bash: syntax error near unexpected token `('

シンタックスエラーだと。。。

解決策

どうやら「(」が特殊文字でエスケープする必要があるとのこと

ファイル名をシングルクォートで囲めばOK!

wc -l  '/var/tmp/20191126-(2,135,397個)テストファイル.csv'

PHPであれば、、

$filePath = '/var/tmp/20191126-(2,135,397個)テストファイル.csv'

$totalRows = exec("wc -l '${filePath}'");

これで正常にできるはず

かんたん

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Linuxコマンドのパイプ

コマンド1 | コマンド2という風に

Linuxコマンドの基本であるパイプ。
コマンド1 | コマンド2 という風に書いて、
複数コマンドを組み合わせて使えます。

コマンド1によってターミナルに表示される文字に対して、
コマンド2を実行します。

具体例

ls | wc -l

ls | wc -l

lsコマンドは存在するファイルを表示するコマンド。
wcコマンドは行数、文字数を表示するコマンド、
-lは行のみを表示するオプション。

lsコマンドでファイルを全て表示して、
wc -lコマンドで行数を表示する。
このように組み合わせて、ファイル数を数えるといった使い方が出来ます。

grep 文字列 ファイル名 | 文字列 ファイル名

grep 文字列 ファイル名 | 文字列 ファイル名
grep c 101.cpp | grep d 101.cpp 

grepコマンドは文字列を、入力したファイル名のファイルから見つけて、
該当する行を表示してくれます。
この例ではgrepを2回使っています。

なので、先に入力したgrepコマンドで101.cppからcを含む行を表示。
表示された文字に対して後から入力したgrepコマンドで101.cppからdを含む行を表示。
結果的に101.cppからcとdを含んだ行を抽出して表示してくれます。

コマンドは3つ以上でも使える

先に書いたように、表示された内容に対してコマンドを実行するだけ。
なので

コマンド1 | コマンド2 | コマンド3 | コマンド4 | コマンド5...

という風に大量のコマンドを繋げることも可能。
例にあげたコマンド以外でももちろん利用できます。

標準であるコマンドとパイプを使えば
ターミナル操作で殆どのことができるので、
使ったことがなければ是非活用してください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Linux プロセス

今回はlinuxのプロセス
つまり稼動経緯について書きます。

プロセス

WEBサーバやコマンドなどLinux上で実行されている処理
プロセスはプロセス名とプロセスIDという番号が自動的に付与されてます。

プロセスの性質として

  • プロセス毎に自分だけのメモリを割り当てられる
  • WEBサーバなどネットワーク機能を利用するプロセスはポートを専有する

1つのCPUが一度に実行できるプロセスは1つだけなので
基本格プロセスが順番に使っている形です。

psコマンド (プロセスを確認)

ターミナル
$ ps 

確認例
 PID TTY           TIME CMD
 1139 ttys000    0:00.03 -bash

psコマンドのオプション

オプション名 意味
-a 自分以外のユーザーのプロセスも表示する。
-r 実行中のプロセスのみを表示する。
-u ユーザー名とプロセスが実行された時刻を表示する。
-aux 実行中のすべてのプロセスに関してCPU使用率などの詳細な情報つきで表示する。

| (パイプ)処理 (複数のコマンドを組み合わせ)

パイプ処理とは、あるコマンドの結果を次のコマンドに渡す処理のことです。パイプ処理を用いたコマンドの組み合わせは以下の様になります。

ターミナル
$ <最初に実行されるコマンド> | <右の結果を受けて最終的な結果を返すコマンド>

例
$ cd ~ #ホームディレクトリに移動
$ ls | grep p  #ホームディレクトリ以下のファイル群から 'p'という文字が含まれるものだけを表示
$ ps aux | grep mysql | grep -v grep  #mysqlサーバーの実行プロセスを探しだして表示

grepコマンド

grepコマンドは特定の文字列が含まれる一行を抽出するためのコマンドです。

ターミナル
grep [検索ファイル] [検索パターン]

kill <...> (プロセスを終了)

プロセスIDに対して特定のコマンドを実行することで、プロセスを再起動したり、強制終了したりできます。

ターミナル
$ kill [プロセスID] # プロセスを終了させる
$ kill -9 [プロセスID] # プロセスを強制終了させる

強制終了の場合、オプションで-9をつけます。
通常のkillコマンドで削除できない場合はこちらを使用。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

linuxでリンクを貼ろう!

ネストの深いディレクトリにアクセスしやすくなる。シンボリックリンクは最強最高!

最強最高lnコマンド!!!

Macだったらエイリアス、Windowsだったらショートカット。便利なこいつらをLinuxではリンクを貼るといい、lnコマンドで再現できます。
こんな感じ

~$ ls
Desktop  Documents
~$ touch Documents/test/test2/test3/hoge.txt
~$ ln Documents/test/test2/test3/ -s test3
~$ cd test3
~/test3$ ls
hoge.txt

無駄に深層にあるディレクトリのtest3に簡単にアクセスできているのがわかります。

lnコマンドでリンクをはろう

lnコマンドで貼れるリンクには以下の2種類があります。

  • ハードリンク
  • シンボリックリンク

ハードリンク

エイリアスやショートカットと違い、一つのファイルに複数の名前を付けるようなイメージで扱われるのがハードリンクで,
オプション無しのlnコマンドで生成できます。

~$ ln file1 file2

file1とfile2は、名前違いで同じデータを参照しており、どちらもオリジナルデータです。最後の1つのハードリンクが消えて初めて参照しているデータが削除されます。

ちなみにディレクトリのハードリンクは作れない。

シンボリックリンク

こいつは例でも見せた見慣れた挙動を見せます。-sオプションをつけたlnコマンドで生成できます。

~$ ln -s file1 file2

これでfile1のシンボリックリンクとしてfile2が作られました。シンボリックリンクは、lsコマンドを用いると水色にハイライトされます。

ハードリンクと違いfile2にはfile1のアドレスが保存されているだけだので、file1が別のディレクトリに移動したり削除されたりすると使えなくなります。(リンクが壊れる)

シンボリックリンクはディレクトリでも作れてとても便利なので、ハードリンクよりよく使われるぞ

あとがき

lsコマンドのハイライト機能は正確にはls --color=autoの機能なのでaliasに設定されていなければハイライト入らなかったりする。
いっちばん最初の例とか絶対見にくいってわかってるんだけどどうもこれ以上にいい例が浮かばなかった...

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Linuxカーネル内のリスト型データ構造とその操作

list in linux kernel

カーネルに於けるリスト型データ構造

LinuxカーネルはCで書かれており、C言語には標準でリストが無い。

どうやってリストを作るかは実装した本人次第だ。

Linuxカーネルのような大規模なコードでは、リストの標準化を行っている。

その実装はCの特異な言語仕様を駆使したものであり、Cをある程度理解していないとかなり難しい。

実装

リストにしたいデータ構造(構造体)に特殊なデータ構造をメンバとして持たせる事で、リストを実装している。

struct student_entry {
    char    *name;
    int     num;
    struct list_head head;
};

以降、このデータ構造をサンプルとする。

list_head

list_head自体は至極シンプルなデータ構造で、前後の要素のポインタを持つだけだ。

struct list_head {
    struct list_head *next, *prev;
};

つまり、リストとして繋がっているのはあくまでlist_head同士である。

それをメンバとして持つ構造体をリストとして操作する為に使うのが、非常に複雑な仕組みだ。

リスト操作

初期化

リストの初期化はマクロLIST_HEAD(name)で行う。

nameはリストにしたいデータ構造の名前を指定する。

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)

サンプル

LIST_HEAD(student_list);

struct student_entry {
    char *name;
    int num;
    struct list_head head;
};

これでstudent_entryというリストの要素の型とstudent_listという名前のリストを定義する。

追加

list_add

カーネルでの定義は少し複雑なので、動きは変えずに少しシンプルに書く

void list_add(struct list_head *new, struct list_head *head) {
    struct list_head *next = head->next;
    next->prev = new;
    new->next = next;
    new->prev = head;
    head->next = new;
}

サンプル

struct student_entry *e = malloc(sizeof(student_entry));
list_add(&e->head, &student_list);

list_add_tail

また少し簡略化

感の良い方は何かに気づくと思うが詳細は後で

void list_add_tail(struct list_head *new, struct list_head *head) {
    struct list_head *prev = head->prev;
    head->prev = new;
    new->next = head;
    new->prev = prev;
    prev->next = new;
}

削除

list_del
リストの前の要素のnextを次の要素に、

リストの次の要素のprevを前の要素にする事でリストから削除する。

void list_del(struct list_head *entry) {
    struct list_head *next = entry->next, *prev = entry->prev;
    next->prev = prev;
    prev->next = next;
    next = LIST_POISON1;
    prev = LIST_POISON2;
}

また、削除する要素のnextprevにはNULLではない値を入れる。

走査

リストに対する走査も複数あり、マクロで定義されたfor文が多い。

ここでは、リストの各要素に対して操作を行うlist_for_each_entryを例に解説する。

#define list_for_each_entry(pos, head, member)              \
    for (pos = list_first_entry(head, typeof(*pos), member);    \
         &pos->member != (head);                    \
         pos = list_next_entry(pos, member))

posに指定したリストの先頭要素を代入し、リスト末尾まで走査するfor文。

サンプル

LIST_HEAD(student_list);

struct student_entry {
    char *name;
    int num;
    struct list_head head;
};

struct student_entry *e = malloc(sizeof(student_entry));
e->name = "hoge";
e->num = 1;
list_add(&e->head, &student_list);

struct student_entry *itr;
list_for_each_entry(itr, &student_list, head) {
    printf("%s %d\n", itr->name, itr->num);
}

マクロ

上で解説した事がわかれば、使用する上では充分だろう。

しかし完全に理解できていない。

それぞれ簡略化して説明した部分を改めて掘り下げる。

本当のlist_add

実際のカーネル内でのlist_addの定義は

static inline void list_add(struct list_head *new, struct list_head *head)
{
    __list_add(new, head, head->next);
}

__list_addを呼び出している。

また、list_add_tail

static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
    __list_add(new, head->prev, head);
}

引数が違うだけで、同じように__list_addを呼び出している。

では__list_addはどうなっているのか

static inline void __list_add(struct list_head *new,
                  struct list_head *prev,
                  struct list_head *next)
{
    if (!__list_add_valid(new, prev, next))
        return;

    next->prev = new;
    new->next = next;
    new->prev = prev;
    WRITE_ONCE(prev->next, new);
}

まず最初の__list_add_validだが、CONFIG_DEBUG_LISTが定義されていない場合はただtrueを返す。

#ifdef CONFIG_DEBUG_LIST
extern bool __list_add_valid(struct list_head *new, 
                struct list_head *prev,
                struct list_head *next);
#else
static inline bool __list_add_valid(struct list_head *new, 
                struct list_head *prev,
                struct list_head *next) {
    return true;
}

CONFIG_DEBUG_LISTが定義されていた場合はlist_debug.cで定義されている

bool __list_add_valid(struct list_head *new, struct list_head *prev,
              struct list_head *next)
{
    if (CHECK_DATA_CORRUPTION(next->prev != prev,
            "list_add corruption. next->prev should be prev (%px), but was %px. (next=%px).\n",
            prev, next->prev, next) ||
        CHECK_DATA_CORRUPTION(prev->next != next,
            "list_add corruption. prev->next should be next (%px), but was %px. (prev=%px).\n",
            next, prev->next, prev) ||
        CHECK_DATA_CORRUPTION(new == prev || new == next,
            "list_add double add: new=%px, prev=%px, next=%px.\n",
            new, prev, next))
        return false;

    return true;
}

~めんどくさい~

next->prev != prev prev->next != next new == prev のいずれかがtrueだった場合、(場合によっては警告を出し、)falseを返す。

次に、next->prevnewにするなどしているが

    next->prev = new;
    new->next = next;
    new->prev = prev;
    WRITE_ONCE(prev->next, new);

WRITE_ONCEとは

static __always_inline void __write_once_size(volatile void *p, void *res, int size)
{
    switch (size) {
    case 1: *(volatile __u8 *)p = *(__u8 *)res; break;
    case 2: *(volatile __u16 *)p = *(__u16 *)res; break;
    case 4: *(volatile __u32 *)p = *(__u32 *)res; break;
    case 8: *(volatile __u64 *)p = *(__u64 *)res; break;
    default:
        barrier();
        __builtin_memcpy((void *)p, (const void *)res, size);
        barrier();
    }
}

#define WRITE_ONCE(x, val) \
({                          \
    union { typeof(x) __val; char __c[1]; } __u =   \
        { .__val = (__force typeof(x)) (val) }; \
    __write_once_size(&(x), __u.__c, sizeof(x));    \
    __u.__val;                  \
})

簡潔に言うと、gccによって余計な最適化が行われる事を防ぎながら代入を行っている。

即ち、prev->next = newと読み替えても本質的な意味は変わらない。

本当のlist_for_each_entry

サンプルではlist_for_each_entry(itr, &student_list, head) {

定義は変わらない。

#define list_for_each_entry(pos, head, member)              \
    for (pos = list_first_entry(head, typeof(*pos), member);    \
         &pos->member != (head);                    \
         pos = list_next_entry(pos, member))

しかし、この中のlist_first_entrylist_next_entryはどうなっているのか。

#define list_first_entry(ptr, type, member) \
    list_entry((ptr)->next, type, member)

で、またラッパー

#define list_entry(ptr, type, member) \
    container_of(ptr, type, member)

またラッパー。

そしてこのcontainer_ofは超重要頻出マクロで、受験生なら覚えるべき。

kernel.hで定義されている。

#define container_of(ptr, type, member) ({              \
    void *__mptr = (void *)(ptr);                   \
    BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&   \
             !__same_type(*(ptr), void),            \
             "pointer type mismatch in container_of()");    \
    ((type *)(__mptr - offsetof(type, member))); })

早速またマクロ

まずBUILD_BUG_ON_MSG

名前の通り、第一引数がtrueならビルド時にエラーメッセージを出力する。

第一引数は

!__same_type(*(ptr), ((type *)0)->member) && !__same_type(*(ptr), void)

__same_typeは名前通り引数の方が一致しているか返すマクロ

つまりこの行は

*ptr((type*)0)->memberの型が異なり、かつ*ptrvoid型で無い時にビルドエラーを発生させる

次の行が本質的で

    ((type *)(__mptr - offsetof(type, member))); })

__mptrvoid*にキャストしたptr

また別のマクロがある

offsetofも名前通り、memberを持つtypeでの、memberのオフセットを求める。

#define offsetof(type, member) ((size_t) &((type*)0)->member)

よって展開すると、container_of

    ((type*)((void*)ptr - ((size_t) &((type*)0)->member)));

何をしているか簡潔に言うと

ptrmemberというメンバ名で持つtype型のポインタを求めている

コレが理解出来れば良いだろう。

本題に戻る。

list_for_each_entryの理解の為、マクロを少しずつ展開してみると

list_for_each_entry(itr, &student_list, head) {

for (itr = list_first_entry(&student_list, typeof(*itr), head);
        &itr->head != student_list;
        itr = list_next_entry(itr, head))

となり、さらに

for (itr = container_of((&student_list)->next, typeof(*itr), head);
        &itr->head != student_list;
        itr = container_of(itr->head.next, typeof(*itr), head))

となる

つまり、サンプルコードのマクロを少し展開すると

struct list_head student_list { &student_list, &student_list};

struct student_entry {
    char *name;
    int num;
    struct list_head head;
};

struct student_entry *e = malloc(sizeof(student_entry));
e->name = "hoge";
e->num = 1;
list_add(&e->head, &student_list);

struct student_entry *itr;
for(itr = container_of((&student_list)->next, struct student_entry, head);
    &itr->head != student_list;
    itr = container_of(itr->head.next, struct student_entry, head)) {
    printf("%s %d\n", itr->name, itr->num);
}
  • struct student_entry *型のitrに、リストの先頭要素を代入。
  • headのアドレスがstudent_entryになる(つまりリスト終端)まで
  • itritr->head.nextを持つリストの要素(リストの次の要素)で更新

sample code

#include <stdio.h>
#include <stdlib.h>

struct list_head list_head;

struct list_head  {
    struct list_head *next, *prev;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)

#define offsetof(type, member) ((size_t) &((type *)0)->member)

#define container_of(ptr, type, member) ({      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type, member) );})

#define list_entry(ptr, type, member) \
    container_of(ptr, type, member)

#define list_first_entry(ptr, type, member) \
    list_entry((ptr)->next, type, member)

#define list_next_entry(pos, member) \
    list_entry((pos)->member.next, typeof(*(pos)), member)

#define list_for_each_entry(pos, head, member)              \
    for (pos = list_first_entry(head, typeof(*pos), member);    \
         &pos->member != (head);                    \
         pos = list_next_entry(pos, member))

void list_add(struct list_head *new, struct list_head *head) {
    struct list_head *next = head->next;
    next->prev = new;
    new->next = next;
    new->prev = head;
    head->next = new;
}

LIST_HEAD(student_list);

struct student_entry {
    char *name;
    int num;
    struct list_head head;
};

int main() {
    struct student_entry *a = malloc(sizeof(struct student_entry));
    a->name = "hoge";
    a->num = 1;
    struct student_entry *b = malloc(sizeof(struct student_entry));
    b->name = "fuga";
    b->num = 2;

    struct student_entry *itr;

    list_add(&b->head, &student_list);
    list_add(&a->head, &student_list);

    list_for_each_entry(itr, &student_list, head) {
        printf("%s %d\n", itr->name, itr->num);
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LinuxでHDDの温度を計る

はじめに

ubuntuでcpuの温度を取得する方法を調べていたらhddの温度も
取得できるらしいことを知った

環境は Ubuntu18.0.4だがCentOS系や他ディストリも基本的にやり方は同じ

hddtempを使う

$ apt install hddtemp
(省略)
$ hddtemp /dev/sda
/dev/sda: HGST HTS545025A7E380: 35°C

hddtemp の引数でドライブを指定。*ドライブを指定しないと使えない
/dev/以下は環境により読み替えが必要。

inxiを使う

$ apt install inxi
(省略)
$ inxi -xD
Drives:    HDD Total Size: 250.1GB (16.8% used)
           ID-1: /dev/sda model: HGST_HTS545025A7 size: 250.1GB temp: 35C

psensorを使う(GUI)

これはCPUの温度計測でつかったものと同じやつ

$ apt install psensor
(省略)
$ psensor

Screenshot from 2019-11-26 18-55-20.png

参考にしたサイト

https://linuxconfig.org/obtain-hard-drive-temperature-information-using-linux
https://www.2daygeek.com/view-check-cpu-hard-disk-temperature-linux/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【最速メモシリーズ】Vagrantで仮想環境をサクッと作る!

前置き

とりあえず早く仮想環境を準備したい!という方に。細かい説明は入れてません。
解説は後々に記載したいと思います。

前提条件

  • ホストはWindows10(未検証ですがおそらくMacもできます)
  • Vagrant 2.2.6
  • VirtualBox 6.0.14
  • 仮想環境のOSはCentOS7を導入するとします
  • ターミナルはGitBash使いました(Windowsの方はコマンドプロンプトやPowershellでも大丈夫です、macはターミナルで)

方法

下準備

1.pluginを更新

vagrant plugin update

2.hostsupdaterを入れる

vagrant plugin install vagrant-hostsupdater

3.適当にディレクトリを準備してVagrantfileを生成

vagrant init --minimal centos/7

4.Vagrantfileを下記に修正

Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"
  config.vm.provider "virtualbox" do |v|
   v.customize ["modifyvm", :id, "--ostype", "RedHat_64"]
  end
end

5.vagrantを立ち上げる

vagrant up

6.sshでゲストOSへ

vagrant ssh

これでひとまずは仮想環境の準備はできる(汗)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

オフラインでパッケージをインストールする

オフラインでインストールするには?

yumコマンドの利用

Linuxにてインストールする際、利用するコマンドはyumです。
yumと聞くとオンラインでのインストールをイメージするかもしれませんが、オフラインでもインストール出来ます。

# mount -t iso9660 /dev/cdrom /media
[定型文]
# yum --disablerepo=* --enablerepo=local_dvd install <インストールしたいもの> 

引用

CentOSオフライン環境でパッケージグループのyumインストール

https://densan-hoshigumi.com/server/centos-offlineinstall-package#DVDyum

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

isoをマウントする

isoをマウントするには?

mountコマンドの利用

Linuxではmountコマンドを使用します。
しかし、サーバにcdromやmediaを搭載するディレクトリがあるとは限りません。
存在しない場合はディレクトリから作成し、作成したディレクトリへisoをテラタームなどを用いて転送します。
サーバにisoを持ってきた後、isoマウントする方法をここでは説明します。

①まず、現在のディレクトリ内にisoファイルが存在することを確認します。

# ls -l /media
-rw-r--r--. 1 root root 531628032  4月 17  2019 CentOS-7-x86_64-NetInstall-1810.iso

②次に対象のisoをマウントします。

[定型文]
# mount -t iso9660 <isoイメージファイル> <マウント場所>

# mount -t iso9660 /dev/cdrom /media

③マウントされたのか、dfコマンドにて確認します。

# df -T

アンマウントされるには?

umountコマンドの利用

[定型文]
# umount <アンマウントするディレクトリ>

[使用例]
# umount /media

引用

DVD-ROMイメージファイルをマウントしてデータを参照

http://ossfan.net/setup/linux-17.html

isoイメージをマウントする方法

https://www.server-memo.net/memo/iso-mount.html

以上がisoのマウント方法でした。
最後までお読みいただきありがとうございました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

リモートのLinuxを手元のWindowsで操作する(GUI編)

リモートのLinuxを手元のWindowsで操作する(GUI編)

知識をアップデートしたのでメモ。

概要

リモートのLinux機を自分の手元のWindowsで操作する。
SSH経由でX11に接続し、GUI操作できるようにする。

設定の流れ

  • Linux機のSSHサーバーの設定を行う
  • WindowsにX server(VcXsrv)をインストールする
  • WindowsのputtyからLinux機にssh接続する
  • 動作テストをする

Linux機のSSHサーバーの設定を行う

設定ファイルを修正する。

$ sudo vi /etc/ssh/sshd_config

書き換える内容(抜粋)。もとから設定されているならそのままでOK。

sshd_config
X11Forwarding yes

書き換えたらサービスを起動。

# systemctl start sshd.service

WindowsにX server(VcXsrv)をインストールする

下記からVcXsrvをダウンロードする。

VcXsrv Windows X Server download | SourceForge.net

インストーラーを起動してインストールする。
設定は全部初期値。

vcxsrv-installer.jpg

スタートメニューから起動する。
初回は設定を色々きかれるが、全部デフォルトでOK。

xlaunch.jpg

WindowsのputtyからLinux機にssh接続する

puttyを起動して、下記の項目にチェックする。

Connection -> SSH -> X11 -> Enable X11 forwarding

putt-x11.jpg

Linux機にログインする。

putty-success.jpg

動作テストをする

ターミナルから下記コマンドを実行する。
(X11のアプリならどれでもOK)

動作テスト
$ nautilus

LinuxのGUIアプリがWindows上で表示される。

x11-windows.jpg

ファイルをダブルクリックするとLinux機内のアプリで表示される。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

リモートのLinuxを手元のWindowsで操作する(CUI編)

リモートのLinuxを手元のWindowsで操作する(CUI編)

概要

リモートのLinux機を自分の手元のWindowsで操作する。
操作はCUIのみとし、SSH経由で接続する。

設定の流れ

  • Linux機でSSH接続用のサーバー設定を行う
  • ファイアウォールを設定する
  • Windows機にSSH接続用のクライアントソフトをインストールする
  • SSH接続を実際に行う

Linux機でSSH接続用のサーバー設定を行う

SSHサーバーの設定を行う

設定ファイルを修正する。

$ sudo vi /etc/ssh/sshd_config

書き換える内容(抜粋)。もとから設定されているならそのままでOK。
X11Forwading yesは今後GUIのリモート接続をするための設定。

Port 22
HostKey /etc/ssh/ssh_host_rsa_key
PermitRootLogin no
PasswordAuthentication yes
X11Forwarding yes

書き換えたらサービスを起動。

# systemctl start sshd.service

ファイアウォールを設定する

ssh接続を許可する。(既に設定済みなら不要)

# firewall-cmd --permanent --add-service=ssh

Windows機にSSH接続用のクライアントソフトをインストールする

下記から「putty-gdi-年月日.zip」をダウンロードする

iceiv+putty

zipを解凍する。場所はどこでもよい。
これでインストールは完了。

SSH接続を実際に行う

インストールしたフォルダの中は下記のようになっている。
putty.exeをWクリックして起動する。

putty-exe.jpg

下記のような画面が表示される。

<LinuxのIPアドレス>の箇所に実際のIPアドレスを入力して
Openボタンをクリックする。

putty-connect.jpg

ログイン名とパスワードを聞かれるので入力する。

パスワードは画面に何も表示されないが入力は受け付けられている。

putty-login.jpg

Linux機にログインが成功する。

後はLinux機に直接ログインした時と同様に操作ができる。

putty-success.jpg

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RHEL5,6,7,8で変更された主要まとめ

RHEL5,6,7,8で変更された主要まとめ

RHELのバージョン混在環境で、困惑するのでまとめてみました。
まあ、今更RHEL5はないでしょうが一応、記載しておきます。
また、調査しても分からない箇所もありましたので、追々追加していきます。

パッケージ RHEL 5 RHEL 6 RHEL 7 RHEL 8
カーネル 2.6.18 2.6.32 3.10.0 4.18
Grub Grub 0.97 Grub 0.97 Grub2 v2.00
GUI Gnome 2.16 Gnome 2.28 Gnome 3.8 Gnome 3.28
起動シーケンス SVR4 init Upstart systemd systemd
Loging Syslog Rsyslog journalctl plus Rsyslog journalctl plus Rsyslog
User Password MD5 SHA-512 SHA-512 SHA-512
パッケージ管理 yum
rpm
yum
rpm
yum
rpm
dnf
yum
rpm
時刻同期 ntp ntp ntp
chrony
chrony
ディスプレイサーバ Xorg Xorg Xorg Wayland
パケットフィルタリング iptables iptables
firewalld
iptables
firewalld
nftable

RHEL8の主なバージョン
OpenSSL 1.1.1、TLS 1.3,GCC 8.2、OpenJDK 11/8などがサポートされる。PythonはPython 3.6がデフォルト、Node.jsのサポートや、PHP 7.2、Ruby 2.5、、Perl 5.26などが提供される。データベースはMariaDB 10.3、MySQL 8.0、PostgreSQL 10/9.6、redis 5、Apache HTTP 2.4、nginx 1.14がデフォルト。

サービス系コマンド

RHEL 7,8では、サービス起動デーモンとして、SysVinit/Upstartに代わり、systemdが導入されました。これにより、サービス系コマンドが大幅に変更されています。RHEL8でもsystemdが採用されていることからRHEL7とは差異はありません。

サービス逐次起動系

処理内容 RHEL 5,6 RHEL 7,8
状態の表示(サービス単位) /sbin/service ※1 status /usr/bin/systemctl status
状態の表示(全サービス) /sbin/service --status-all /usr/bin/systemctl list-units ※2--type service
起動 /sbin/service start /usr/bin/systemctl start
終了 /sbin/service stop /usr/bin/systemctl stop
強制終了 kill -9 PID kill -s 9
再起動 /sbin/service <service_name? restart /usr/bin/systemctl restart
設定反映 /sbin/service reload /usr/bin/systemctl reload

※1:/etc/init.d/service_nameでも同様
※2:list-unitsは省略可

サービス自動起動系

処理内容 RHEL 5,6 RHEL 7,8
(全サービス)定義の表示 ls /etc/init.d/ /usr/bin/systemctl list-unit-files --type
(サービス単位の)定義の登録 /sbin/chkconfig --add /usr/bin/systemctl daemon-reload
※3
自動起動の確認 /sbin/chkconfig --list /usr/bin/systemctl is-enabled
自動起動の有効化 /sbin/chkconfig on /usr/bin/systemctl enable
自動起動の無効化 /sbin/chkconfig off /usr/bin/systemctl disable

※3:Unitファイルを再読み込みすることにより登録される

systemdでは、「Unit」という単位でさまざまな処理を行います。従来のサービスに相当する処理は「.service」という拡張子がつくファイルとして管理されており、サービス関連の処理を行うときは、この名前を指定します。Unitには、ほかにもマウントポイントの処理を行う「.mount」、デバイスの処理を行う「.device」、Unitをグループ化する「.target」などがあります。

また、自動起動の登録を行ったUnitは、「/usr/lib/systemd/system/unit_name」内の[Install]セクションのWantedByオプションで指定されているUnitのディレクトリ(例:/etc/systemd/system/multi-user.target.wants/)にシンボリックリンクが張られることにより、自動起動が有効となります。

RHEL 6と同じコマンドを利用したい方は……

RHEL 7,8のserviceコマンドやchkconfigコマンドは、systemctlコマンドにリダイレクトするシェルスクリプトとなっているのでそのまま利用できます。

  • サービスの一時停止
$ sudo service crond stop
Redirecting to /bin/systemctl stop crond.service
  • サービスの自動起動の無効化
$ sudo chkconfig crond off
Note: Forwarding request to 'systemctl disable crond.service'. rm '/etc/systemd/system/multi-user.target.wants/crond.service' 

ただし、chkconfig --listについては、出力結果にも注意書きがあるとおり、一部のサービスしか表示されないため注意が必要です。

$ chkconfig --list
Note: This output shows SysV services only and does not include native systemd services. SysV configuration data might be overridden by native systemd configuration. 

ランレベル

RHEL 7,8では、従来のランレベルに相当する起動モードも「.target」という拡張子がつくUnitで管理されるようになっています。これまでのランレベルとの対応は、下記のとおりです。なお、targetファイルを自作して、独自の起動モードを利用することも可能です。

処理内容 RHEL 5,6 RHEL 7,8
システム停止 0 poweroff.target
シングルユーザモード 1 rescue.target
マルチユーザモード 3 multi-user.target
グラフィカルモード 5 graphical.target
再起動 6 reboot.target
緊急モード N/A mergency.target

通常の起動の際は、いずれかのtargetへのシンボリックリンク(通常はmulti-user.targetかgraphical.target)となっているdefault.targetが参照されます。

ランレベル系コマンドの一覧

処理内容 RHEL 5,6 RHEL 7,8
起動モードの変更 telinit
init
systemctl isolate
起動モードの認 runlevel systemctl list-units --type target
Default起動モードの変更 /etc/inittabの編集 sudo systemctl set-default
Default起動モードの確認 /etc/inittabの参照 systemctl get-default
  • rescue.target(従来のシングルユーザモード相当)に変更
$ sudo systemctl isolate rescue.target
  • デフォルトの起動モードをマルチユーザモードへ変更
$ sudo systemctl set-default multi-user.target
$ rm '/etc/systemd/system/default.target'
$ ln -s '/usr/lib/systemd/system/multi-user.target' '/etc/systemd/system/default.target' 
  • RHEL 6と同じコマンドを利用したい……

現在と1つ前のランレベルを表示するrunlevelコマンド、ランレベルを一時的に変更するtelinit(init)コマンドも利用できます。ただし、/etc/inittabは、ファイルそのものはあるもののコメントだけとなっているため、標準起動モードの変更については、systemctl set-default の実行が必要なようです。

ログ確認系コマンド

systemdによって起動されたUnitのログは、/var/log/journal以下にバイナリ形式で保存されるようになっています。そのため、ログの確認にはjournalctlコマンドを利用します。

ログ確認系コマンドの一覧は下記のとおりです。

処理内容 RHEL 5,6 RHEL 7,8
(サービス単位の)ログ確認 cat /var/log/ journalctl -u
ログの更新監視 tail -f /var/log/ journalctl -f -u
起動ログの確認 dmesg systemctl journalctl --dmesg

journalctlによる表示には、デフォルトでページャ(less)で表示されます。パイプ処理などでページャを利用したくない場合は、--no-pagerオプションを付加します。また、--sinceオプションで相対時間(例:30 min ago)、絶対時間(2015-04-30)以降のログ出力、--outputオプションでJSONなどの各種形式で出力、-bオプションでN世代前のブートログ表示など、数多くの機能を備えています。
ただし、デフォルト設定のままの場合、/run/systemd/journal以下にログが書き込まれ、再起動すると消えてしまうので注意が必要です。再起動後もログを残すには、/var/log/journalを作成して、journaldの再起動(systemctl restart systemd-journald)を行う必要があります。

ネットワーク系コマンド

RHEL 7,8では、ifconfigやnetstatといった馴染みのあるコマンドが含まれている、net-toolsパーッケージがインストールされなくなりました。

ネットワーク系コマンドの一覧は下記のとおりです。なお、ipコマンドのオプションは、一意な文字列まで入力すれば認識してくれるので、短縮表記例も併記しておきます。

処理内容 RHEL 5,6 RHEL 7,8(フル表記) RHEL 7,8(短縮表記例)
全アクティブインターフェイスの情報表示 /sbin/ifconfig /sbin/ip address show
or /sbin/ip link show
/sbin/ip a
or /sbin/ip
特定インターフェイスの情報表示 /sbin/ifconfig eth0 /sbin/ip address show
dev enp0s3
/sbin/ip a s
dev enp0s3
ルーティングテーブルの表示 /sbin/route /sbin/ip route /sbin/ip r
デフォルトゲートウェイの追加 /sbin/route add default gw xxx.xxx.xxx.xxx ip route add default via xxx.xxx.xxx.xxx /sbin/ip r a default via xxx.xxx.xxx.xxx
デフォルトゲートウェイの削除 /sbin/route del default gw xxx.xxx.xxx.xxx ip route del default via xxx.xxx.xxx.xxx /sbin/ip r d default via xxx.xxx.xxx.xxx
TCPの接続状態の表示 /bin/netstat -tan ss -tan 左に同じ
インターフェイスごとの統計情報 /bin/netstat -i ip -s link ip -s
ARPテーブルの表示 /sbin/arp -n /sbin/ip neighbour /sbin/ip n

MAC Address /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/udev/rules.d/70-persistent-net.rules

RHEL 6と同じコマンドを利用したい方は……
net-toolsパッケージをインストールすれば、RHEL 6で使用していたネットワーク系コマンドはすべて利用可能となります。

NetworkManager系コマンド

NetworkManagerは、RHEL 4から搭載されているネットワークユーティリティで、RHEL 7で新しく追加されたわけではありません。しかし、RHEL 7より、ネットワーク設定にはこのユーティリティを使用することが推奨されるようになったので、今後は利用頻度が高くなると思います。

NetworkManagerには、X上で動作するGUIツールのほか、ターミナル上でGUIで設定できるnmtuiコマンド、CUIで設定するnmcliコマンドがあります。ここでは、最も利用しやすいとnmcliコマンドを用いたNetworkManager系コマンドを下記に紹介します。

なお、デバイスを示す「デバイス名」と、接続に名前をつけた「接続名」は異なることがあるので注意してください。

処理内容 nmcliコマンド(フル表記) nmcliコマンド(短縮表記例)
デバイス一覧の表示 /usr/bin/nmcli device /usr/bin/nmcli d
デバイス情報の表示 /usr/bin/nmcli device
show device_name
/usr/bin/nmcli d sh device_name
接続の作成 /usr/bin/nmcli connection add type type_name ifname if_name con-name connection_name /usr/bin/nmcli c a type type_name ifname if_name con-name connection_name
接続の削除 /usr/bin/nmcli connection delete connection_name /usr/bin/nmcli c de connection_name
接続一覧の表示 /usr/bin/nmcli connection /usr/bin/nmcli c
接続情報の表示(すべて) /usr/bin/nmcli connection show connection_name /usr/bin/nmcli c s connection_name
接続の変更 /usr/bin/nmcli connection modify .... /usr/bin/nmcli c m ...
接続の開始 /usr/bin/nmcli connection up connection_name /usr/bin/nmcli c u connection_name
接続の停止 /usr/bin/nmcli connection down connection_name /usr/bin/nmcli c d connection_name
接続情報の表示(特定フィールド) /usr/bin/nmcli --fields field_name connection show connection_name /usr/bin/nmcli -f field_name c s connection_name

RHEL6でのNetworkManager

デフォルトで NetworkManager サービスが起動するため /etc/sysconfig/network-scripts/ifcfg-XXX の書式が従来と変わっています。

従来の書式で設定ファイルを書く場合は、設定ファイルに下記の1行を追加します。
NM_CONTROLLED=no

もしくは NetworkManager サービスを停止します。

# chkconfig NetworkManager off
# service NetworkManager stop

RHEL6でのethX と MAC Address の紐付け

RHEL5では/etc/sysconfig/network-scripts/ifcfg-XXXにHWADDRとして記載していたが
RHEL6では、/etc/udev/rules.d/70-persistent-net.rules で指定します。

# cat /etc/udev/rules.d/70-persistent-net.rules
# This file was automatically generated by the /lib/udev/write_net_rules
# program, run by the persistent-net-generator.rules rules file.
#
# You can modify it, as long as you keep each rule on a single
# line, and change only the value of the NAME= key.

# PCI device 0x14e4:0x164c (bnx2) (custom name provided by external tool)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:14:5e:fa:98:a2", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"

# PCI device 0x14e4:0x164c (bnx2) (custom name provided by external tool)
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:14:5e:fa:98:a0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"

が、相変わらず、/etc/sysconfig/network-scripts/ifcfg-ethX にも HWADDR 指定があるので、両方を合わせないといけない。ifcfg-ethX の HWADDR は削除した方が幸せになれるかも知れません。

ロードモジュール

RHEL6では、/etc/modprobe.conf が無くなりました。目的別に対応を説明します。

(1) initrdに投入する内蔵ディスク用のデバイス・ドライバの指定(alias scsi_hostadapterXX)
RHEL5 までは、mkinitrd コマンドは /etc/modporbe.conf をみて、そのサーバを起動するために必要なドライバを含む initrd を作成しました。initrd に含まれる初期化スクリプト init では、下記の例のように必要なドライバを直接 insmod しています。

echo "Loading ehci-hcd.ko module"
insmod /lib/ehci-hcd.ko
echo "Loading ohci-hcd.ko module"
insmod /lib/ohci-hcd.ko
...

RHEL6 では、initrd の作成が dracut に変わって、サーバ個別の initrd ではなく、汎用的な initrd が作成されるようになったので、/etc/modprobe.conf による指定は不要になりました。dracut が作成する initrd では、udev によって、サーバに接続されたデバイスに応じたドライバを自動判別してロードします。

具体的には、initrd に含まれる etc/udev/rules.d/80-drivers.rules のルールから modprobe が呼び出されます。

# cat 80-drivers.rules
# do not edit this file, it will be overwritten on update

ACTION!="add", GOTO="drivers_end"

DRIVER!="?*", ENV{MODALIAS}=="?*", RUN+="/sbin/modprobe -b $env{MODALIAS}"
SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="SD", RUN+="/sbin/modprobe -b tifm_sd"
SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="MS", RUN+="/sbin/modprobe -b tifm_ms"
SUBSYSTEM=="memstick", RUN+="/sbin/modprobe -b --all ms_block mspro_block"
SUBSYSTEM=="i2o", RUN+="/sbin/modprobe -b i2o_block"
SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_device", TEST!="[module/sg]", RUN+="/sbin/modprobe -b sg"
SUBSYSTEM=="module", KERNEL=="parport_pc", RUN+="/sbin/modprobe -b ppdev"

LABEL="drivers_end"

そうは言っても特定のドライバを特定の順序で読み込ませたい場合は、カーネルオプション rdloaddriver にドライバを読み込む順に記載します。具体的には、init スクリプトから下記のスクリプトが実行されて、指定のドライバがロードされます。

# cat cmdline/01parse-kernel.sh
#!/bin/sh

for p in $(getargs rdloaddriver=); do
        modprobe $p
done

dracut が標準で initrd に含めないドライバを使用する際は、dracut の -d オプションで強制的に initrd に入れておきます。dracut については、レッドハットニュースレター:vol.53 - dracut もどうぞ。
http://www.jp.redhat.com/magazine/jp/201102/rhel.html

2) NIC用のデバイス・ドライバの指定(alias ethXX)

サーバ起動後の追加のドライバのロードは、すべて udev で処理されるようになっています。具体的には、rc.sysinit から start_udev したタイミングで、/lib/udev/rules.d/80-drivers.rules に従って自動的に modprobe されます。(dracut 内部の動作と基本的には同じです。)

# cat /lib/udev/rules.d/80-drivers.rules
# do not edit this file, it will be overwritten on update

ACTION!="add", GOTO="drivers_end"

DRIVER!="?*", ENV{MODALIAS}=="?*", RUN+="/sbin/modprobe -b $env{MODALIAS}"
SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="SD", RUN+="/sbin/modprobe -b tifm_sd"
SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="MS", RUN+="/sbin/modprobe -b tifm_ms"
SUBSYSTEM=="memstick", RUN+="/sbin/modprobe -b --all ms_block mspro_block"
SUBSYSTEM=="i2o", RUN+="/sbin/modprobe -b i2o_block"
SUBSYSTEM=="scsi", ENV{DEVTYPE}=="scsi_device", TEST!="[module/sg]", RUN+="/sbin/modprobe -b sg"
SUBSYSTEM=="module", KERNEL=="parport_pc", RUN+="/sbin/modprobe -b ppdev"

LABEL="drivers_end"

ちなみに、udev が必要なドライバを判別する方法は次のとおりです。まず、PCI デバイスなどは、/sys に登録されるとカードに固有の modalias 情報が登録されます。

# cat /sys/devices/pci0000:00/0000:00:06.0/0000:03:00.0/0000:04:00.0/modalias
pci:v000014E4d0000164Csv00001014sd00000342bc02sc00i00

一方、各ドライバは、サポートするデバイスの modalias 情報を持ちます。下記の alias: 部分です。

# modinfo bnx2
filename:       /lib/modules/2.6.32-71.el6.x86_64/kernel/drivers/net/bnx2.ko
firmware:       bnx2/bnx2-rv2p-09ax-5.0.0.j10.fw
firmware:       bnx2/bnx2-rv2p-09-5.0.0.j10.fw
firmware:       bnx2/bnx2-mips-09-5.0.0.j15.fw
firmware:       bnx2/bnx2-rv2p-06-5.0.0.j3.fw
firmware:       bnx2/bnx2-mips-06-5.0.0.j6.fw
version:        2.0.8-j15
license:        GPL
description:    Broadcom NetXtreme II BCM5706/5708/5709/5716 Driver
author:         Michael Chan <mchan@broadcom.com>
srcversion:     8CDA41B3E0DF70A112FBA80
alias:          pci:v000014E4d0000163Csv*sd*bc*sc*i*
alias:          pci:v000014E4d0000163Bsv*sd*bc*sc*i*
alias:          pci:v000014E4d0000163Asv*sd*bc*sc*i*
alias:          pci:v000014E4d00001639sv*sd*bc*sc*i*
alias:          pci:v000014E4d000016ACsv*sd*bc*sc*i*
alias:          pci:v000014E4d000016AAsv*sd*bc*sc*i*
alias:          pci:v000014E4d000016AAsv0000103Csd00003102bc*sc*i*
alias:          pci:v000014E4d0000164Csv*sd*bc*sc*i*
alias:          pci:v000014E4d0000164Asv*sd*bc*sc*i*
alias:          pci:v000014E4d0000164Asv0000103Csd00003106bc*sc*i*
alias:          pci:v000014E4d0000164Asv0000103Csd00003101bc*sc*i*
depends:
vermagic:       2.6.32-71.el6.x86_64 SMP mod_unload modversions
parm:           disable_msi:Disable Message Signaled Interrupt (MSI) (int)

これらの情報は、depmod がまとめて /lib/modules/$(uname -r)/modules.alias に記録しており、「modporbe 」を実行すると modules.alias から必要なドライバを判別して自動的にロードします。/lib/udev/rules.d/80-drivers.rules では、Kernel が udev に通知した modalias を使って modprobe しています。udev に勝手にロードしてほしくないドライバは、/etc/modprobe.d/blacklist.conf 内に blacklist オプションで指定しておきます。

ホスト名操作系コマンド

RHEL 7,8では、ホスト名もsystemdが管理しているため、永続的なホスト名の変更方法も変更されました(hostnameコマンドを利用した一時的なホスト名の変更はRHEL 6と同じです)。

ホスト名操作系コマンドの一覧は下記のとおりです。

処理内容 RHEL 5,6 RHEL 7,8
ホスト名の確認 hostname hostname or hostnamectl
ホスト名の変更(永続的) /etc/sysconfig/networkを編集 hostnamectl set-hostname new_host_name
,/etc/hostnameを編集

なお、「nmcli global hostname new_host_hame」を実行して、NetworkManager経由でも変更することができます。

ファイアウォール系コマンド

RHEL 7では、ファイアウォールとしてfirewalldが導入されました。これは、内部的にはiptablesを利用しているものの、「ゾーン」と呼ばれるiptablesとはまったく異なる機能を提供しているため、コマンド一覧は割愛します(iptabelesサービスとの併用もできません)。

RHEL 8では、ファイアウォールとしてnftablesが新たにiptableと置き換えで実装されたパケットフィルターです。

デフォルトでは nftablesは RHEL 7 での iptables と同様に、firewalld のバックエンドとして動作するので、既に firewalld に移行している場合はあまり気にならないかもしれません。

nftables を利用するメリット

  • フィルターの処理が、線形処理からテーブル探索に(処理速度の高速化)

  • IPv4とIPv6をひとつのコマンドで管理可能に(ip6tables のような、IPv6専用コマンドは使いません)

  • ネットワーク層以外のプロトコルも管理可能に(entablesarptablesは、nftablesに統合されました)

  • 一貫性があり、簡潔な文法(iptables の –dport のようなプロトコル独自の拡張はありません)

モジュール組み込み

aliasの記載もRHEL6,7では変更されている。

RHEL 5 RHEL 6 RHEL 7,8
/etc/modprobe.conf /etc/modprobe.d/
※bondingのaliasはnet-alias.conf
/etc/modprobe.d/
※bondingのaliasはnet-alias.conf

Storage

FS Type,Size

Release Default FS 暗号化 FS Maximum
Volume size File size
RHEL5 ext3 LUKS 4-32TiB 16GiB-2TiB
RHEL6 ext4 LUKS 1EiB 16TiB
RHEL7 xfs LUKS 16EiB 8EiB
RHEL8 xfs LUKS2 16EiB 8EiB

利用可能なFS

Release 利用可能なFS
RHEL5 ext3,ext4,GFS,GFS2,XFS
RHEL6 ext3,ext4,GFS2,XFS
RHEL7 ext3,ext4,GFS2,XFS,Btrfs
RHEL8 XFS,ext3,ext4、NFS、SMB、GFS2、Stratis

Diskパーティション系コマンド

ブート方式 パーティション管理
BIOS MBR形式
UEFI GPT形式
処理内容 MBR形式 GPT形式
サポートするファームウェア BIOS,UEFI UEFI
基本パーティション 最大4 最大128
拡張パーティション 1 無し
拡張パーティション内の論理パーティション 制限無し 無し
ツール fdisk、parted parted,gdisk,gparted
ブートローダの制限 ハードディスクの2.2TB内 9.4ZB(ゼタバイト)
Redhat Linux サポート状況 RHEL 5 x86
RHEL 5 x86_64
RHEL 6 x86
RHEL 6 x86_64
RHEL 6 x86_64
RHEL 7 x86_64
RHEL 8 x86_64

(*)各ディスクの先頭に保存されているMBR(マスター・ブート・レコード)はパーティション・テーブルのデータ長が32bitです。よって2の32乗セクタ×512bytes=約2.2Tbytesとなります。

BIOSとUEFIではパーティション管理形式も異なります。BIOSではMBR形式のみです。一方UEFIではMBR形式とGPT形式がサポートされています。
RHEL5,6ではpartedが OS 標準のRPMとして含まれている。
RHEL7 では gdisk が OS 標準のRPMとして含まれている。

2TBを越えるディスク領域を使用する際の注意事項
パーティション作成にはpartedユーティリティを使用し、GPT(GUIDパーティションテーブル)を使用します。fdiskでは2TBを越えるディスクスペースは扱えません。
Anacondaインストーラーは、GPTをサポートしていない為、2TBを越えるディスクスペースは扱えません。
/boot, / パーティションは 2TB未満のディスク領域にインストールする必要があります。

■■■ ファイルシステム系コマンド ■■■
RHEL 7ではファイルシステムもext4からxfsに変更されています。
・EXT4 と XFS コマンドの参照表

処理内容 ext3 ext4 XFS Btrfs
FS作成 mkfs.ext3 mkfs.ext4 mkfs.xfs mkfs.btrfs
FSをマウントする mount mount mount mount
FSのサイズを変更する resize2fs resize2fs xfs_growfs
[※1]
btrfs filesystem resize
FSの準備を整える e2fsck
fsck.ext3
e2fsck
fsck.ext4
xfs_repair btrfsck
FSのラベルを変更する e2label e2label xfs_admin -L btrfs property
ディスク領域およびファイル使用量を報告 quota,quotaon, repquota quota,quotaon, repquota xfs_quota btrfs quota
FSをデバッグする debugfs debugfs xfs_db
FSの重要なメタデータをファイルに保存する e2image e2image xfs_metadump btrfs-image
FSの情報表示 dumpe2fs dumpe2fs xfs_info
FSのメタデータの変更 tune2fs tune2fs xfs_admin btrfs property
FSのバックアップ dump dump xfsdump btrfs image
FSのリストア restore restore xfsrestore btrfs image
ファイルのディスク上のブロック一覧表示 filefrag filefrag xfs_bmap
FSのデフラグ e4defrag e4defrag xfs_fs btrfs filesystem defragment
FSの一時停止 fsfreeze fsfreeze xfs_freeze,fsfreeze

※1:XFSファイルシステムのサイズは縮小できません。サイズを拡大する場合にのみコマンドを使用します。

XFSの設定のポイント

ほとんどのシステムでは特別なチューニングを行うことなくデフォルトの状態でXFSを利用できますが、要件によっては設定次第で性能が向上する可能性があります。例えば、RAIDアレイ上にXFSを構築する場合、ストライプユニットをRAIDアレイのストライプユニットと一致させることにより、性能向上が期待できます。ストレージデバイスがOSに自身のストライプユニットを通知している場合は、特にユーザーが設定する必要はありません。手動でストライプユニット、ストライプ幅を設定する場合、以下のようにしてファイルシステムを作成します。

# mkfs.xfs -d su=64k,sw=4 /dev/sda1

suはファイルシステムのストライプユニット、swはストライプ幅を意味します。swにはストライピングを構成するハードディスクの数(パリティディスクは含まない)を設定します。

上記の設定をした場合、ジャーナル領域へのログ書き込みのストライプユニットも同様の値に設定されます(上記の例では64kB)。もし同期書き込みが多いワークロードでXFSを使用する場合、ログ書き込みのストライプユニットが大きいと性能低下の原因となることがあります。そのような場合、以下のようにログ書き込みのストライプユニットを最小値(1ブロックサイズ:通常は4kB)に設定すると性能が改善するかもしれません。

# mkfs.xfs -d su=64k,sw=4 -l su=4k /dev/sda1

また、ログ書き込みのオーバヘッドを改善する対処策としては、ログが書き出されるジャーナル領域を、データ用の領域として使用するデバイスとは別に用意するという方法も考えられます。
その場合、以下のようにしてファイルシステムを作成します。

# mkfs.xfs -d su=64k,sw=4 -l logdev=/dev/sdb1 /dev/sda1

上記コマンドでは、データ用の領域を/dev/sda1に、ジャーナル領域を/dev/sdb1に作成しています。

最後に

今回調べてみて、RHEL 7,8での変更点の多さを改めて痛感しました。もはや、これまでのRHELとは別のOSになったような雰囲気すらあります。ただし、RHELにかぎらず、多くのディストリビューションがsystemdへの対応を表明していますので、使いこなせるようになっておきたいところです。そのためにも、今回は詳しくは触れられなかった、Unitの仕組みの理解が不可欠と思いました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LinuxでCPU温度を計測する

環境

ubuntu 18.04.3 LTS

catでtempファイルを直接表示

$ cat /sys/class/thermal/thermal_zone0/temp
58200

ディレクトリの "thermal" 以下はOSやCPUで違うため適宜読み替えが必要。

lm_sensorsを使う

$ apt-get install lm-sensors
(省略)
$ sensors
coretemp-isa-0000
Adapter: ISA adapter
Package id 0:  +60.0°C  (high = +87.0°C, crit = +105.0°C)
Core 0:        +57.0°C  (high = +87.0°C, crit = +105.0°C)
Core 1:        +60.0°C  (high = +87.0°C, crit = +105.0°C)

psensorを使う(GUI)

$ apt-get install psensor
(省略)
$ psensor

Screenshot from 2019-11-26 05-38-36.png

チェックボックスにチェックを入れるとグラフ表示も可能

Screenshot from 2019-11-26 05-42-00.png

xsensorを使う

$ apt-get install xsensors
(省略)
$ xsensors

Screenshot from 2019-11-26 05-46-40.png

おわり

紹介したツールのインストールは他ディストリビューションでも基本的に同じ(未確認)
それぞれ大きな違いはなさそうなのであとは好みで。
HDDの温度も同時に見れるpsensorが便利。

参考サイト
https://wiki.archlinux.jp/index.php/Lm_sensors
https://www.addictivetips.com/ubuntu-linux-tips/check-cpu-temperature-on-linux/
https://www.cyberciti.biz/faq/how-to-check-cpu-temperature-on-ubuntu-linux/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Linux 作業メモ: 時間を進める/戻すコマンド

Linuxのシステム時間を進めたり戻したりするコマンド。テストの時に重宝するのでメモ。


基本的には使うのはこのコマンドのみでOK.
date --set="STRING"


  • 例1. 時間を"4 DEC 2019 15:30:00"へ進めます。
# date
Mon Nov 25 11:41:16 PST 2019
# date --set="4 DEC 2019 15:30:00"
Wed Dec  4 15:30:00 PST 2019


  • 例2. 時間を25 NOV 2019 11:45:00"へ戻します。
# date --set="25 NOV 2019 11:45:00"
Mon Nov 25 11:45:00 PST 2019




便利なので是非ご利用ください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

hostsを使って集中を切らすサイトへのアクセスをブロックする

背景

Macbookを作業専用として使っているが、僕は意志薄弱なのですぐにTwitterやYouTubeを開いてしまう。
これらのサイトドメインへのアクセスをブロックすることで作業中の集中力を上げたい。
ブラウザ(Chrome)のブックマークや拡張機能は他のPCと同期しているので、その辺りは利用したくない。

環境

OS: macOS Catalina v10.15.1
ブラウザ: Google Chrome v78.0.3904.108(Official Build) (64 ビット)

対応

hostsファイルを編集し、対象ドメインの名前解決先を127.0.0.1にすることでアクセスをブロックする。

$ sudo vi /etc/hosts

# 以下追記
127.0.0.1 twitter.com
127.0.0.1 tweetdeck.twitter.com
127.0.0.1 www.youtube.com

設定反映のためにDNSキャッシュを削除する必要がある。
DNSキャッシュはmDNSResponderプロセスが保持している。
Chromeでは、このプロセスへのSIGHUP送信では設定が反映されなかったため、一旦プロセスをKILLする。

$ sudo killall mDNSResponder

確認

ブラウザから今回ブロックしたサイトにアクセスできなくなっていることを確認する。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

aliasの便利コマンドを教えてほしい話

UNIXやLINUX上でコマンドを省略した形で登録することのできるaliasについて紹介する

alias:コマンドの省略形が作成できる

bash

$ alias 登録したい単語='登録したいコマンド'  
$ alias histail='history | grep curl | tail'
$ histail
 3295  curl "http://localhost:8080"
 3296  curl "http://localhost:8080"
 3297  curl "http://localhost:8080"
 3298  curl "http://localhost:8080"

zsh

~/.zshrcにbashと同じように記述することでaliasを登録できる

$ vi ~/.zshrc

alias histail='history | grep curl | tail'
alias rezsh='source ~/.zshrc'
alias redoc='docker-compose stop && yes | docker-compose rm && docker-compose up -d'
alias -g @b64='| base64 '
alias -g @d64='| base64 -D'
alias -g g='|grep '
alias vish='vi ~/.zshrc'

zshにはグローバルエイリアスと呼ばれるエイリアスが登録できる
グローバルエイリアスは普通のエイリアスと違い、呼ばれる場所を問わない(普通のエイリアスは文頭限定)

なので

$ echo aaaaaaa @b64

とすることでbase64エンコードをかけることなどができる
(あまり省略できてないとは言わないでください)

aliasメモ

便利だと思ったaliasをメモ的に列挙しておきたいので、教えてください(他力本願)

alias 元のコマンド 操作説明
rezsh source ~/.zshrc zshの設定ファイルを再読み込みさせる
redoc docker-compose stop && yes | docker-compose rm && docker-compose up -d |docker-composeの再起動を行う
sd docker-compose stop docker-composeを止める
rd docker-compose rm docker-composeの設定を削除する
ud docker-compose up -d docker-composeを立ち上げる
vish vi ~/.zshrc zshの設定ファイルを編集する
@b64 | base64 base64エンコーディングを行う
@d64 | base64 -D base64デコーディングを行う
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む