|||||||||||||||||||||

なんぶ電子

- 更新: 

MariaDBでレプリケーション

MariaDB

データベースバックアップのためにVPSサーバーを新規に構築し、MariaDBでレプリケーションを構成した時の覚書です。

2022/3追記

MariaDBでは、ポリコレ(差別表現の修正)の観点から、バージョン10.5.2から従来SLAVE(スレーブ)、MASTER(マスター)としていた表記の一部を、(REPLICA)レプリカと(PRIMARY)プライマリという表現に変更しています。

コマンドは、たとえば「SHOW SLAVE STATUS」は「SHOW REPLICA STATUS」に、「SHOW MASTER STATUS」は「SHOW BINLOG STATUS」とったように変わっています。

ただ、執筆時点のバージョンでは、すべてのコマンドにおいて修正が完了しているわけではなさそうです。

このページもできる限りそれに沿うように表現したいと思います。プライマリがコピー元、レプリカがコピー先となります。

設定ファイル

MariaDBのサーバー用の設定ファイルはデフォルトで/etc/mysql/mariadb.conf.d/50-server.cnfとなってます。レプリケーションを作成しようという話を読んでいただいているので、通常稼働用の設定はできていると思いますので、そのあたりは省略させていただきます。

レプリケーションにはバイナリログが使われるのでその出力設定を記述します。ちなみにMariaDB内の設定ファイル内では-(半角ハイフン)と_(半角アンダーバー)はどちらを使ってもいいそうです。この記述では_に統一しています。

プライマリの50-server.cnf

[mysqld]
server_id=1001
log_bin=/var/log/mysql/mysql-bin
max_binlog_size =100M
expire_logs_days=10
binlog_format=MIXED

server_idは0~4294967295までの値を指定できます。0や1番とかだとデフォルト値と重なる可能性があるので少し大きな値にします。

log_binはバイナリログの出力場所を指定します。上のように設定するとmysql-bin.123456という形で、連番のついたファイルが作成されます。

バイナリログとはレプリケーションで使う非プレーンテキストのログで、これを使ってプライマリからレプリカへデータを転送します。

max_linlog_sizeでログファイルの基準サイズを指定します。バイナリログはインデックスがついた複数のファイルで構成されますが、これらのファイルのサイズの目安を決めるものです。再起動で別のファイルに切り替わったり、連続したデータのためにサイズをオーバーしたりと指定したサイズぴったりにはなりません。

expire_logs_daysでバイナリログを保存しておく日数を指定します。放っておくとプライマリサーバーにログが溜まってディスクを圧迫するようになるので、バイナリログの賞味期限を決めます。レプリカ用にバイナリログを出力するだけならあまり気にする必要がないかもしれませんが、通信障害が発生してレプリカにデータを送信できなかったりする期間が、ここで設定した期間を上回るとレプリケーションを一から構成し直す必要があります。

binlog_formatはSTATEMENT、ROW、MIXEDがあります。

STATMENTはSQL文を保存します。データ量を削減できるのですが、プライマリとレプリカで異なった結果になる場合もあります(auto_increment や timestamp を利用するケースが思いつきますが、これらは安全に STATEMENT で利用できるそうです)。これに対しては、行(の内容)単位でバイナリログを取得するROWモードを利用することで回避できます。これはログが大きくなるので、MIXEDというSTATEMENTとROWを混在させるモードもあります。

プライマリサーバーの設定ファイルの変更については以上です。

次にレプリカサーバーです。

レプリカの50-server.cnf

[mysqld]
server_id=1020

# リレーログの出力場所
relay-log=/var/log/mysql/mysql-relay-bin

# 以下はさらにレプリカを設定する場合に必要
log_bin=/var/log/mysql/mysql-bin
max_binlog_size = 100M
expire_logs_days=10
binlog_format=MIXED
log_slave_update

レプリカサーバーでも server_id の記述をします。IDなのでプライマリや他のMariaDBサーバーとは違った値を設定してください。

レプリカサーバー側はバイナリログの出力は必須ではありませんが、リレーログという別のログファイルが必要になります。

リレーログは、プライマリから取得したプライマリから来たデータを一時保存しておくものです。すべてのデータはいったんここに格納されたのちにデータベースファイルに反映されます。このログは relay_log_purge のデフォルト値である True の効果により不要になった際に削除されます。

リレーログの出力場所は relay-log に指定します。

もしレプリカのレプリカ(孫)を持ちたい場合は、バイナリログを出力するのに加え、「 log_slave_update 」の記述を加える必要があります。これを記述しないとプライマリから伝わった更新はレプリカのバイナリログには出力されません。

設定ファイルの編集が終わったら、再起動させて読み込ませます。

レプリケーション用のユーザーの作成

設定ができたら今度はコンソールで設定をします。

プライマリサーバーに、レプリケーションを用のユーザーを登録します。root等、GRANT権限のあるユーザーで処理してください。

MariaDB[]> CREATE USER 'rep-user'@'192.168.1.0/255.255.255.0' identified by 'password';
MariaDB[]> GRANT REPLICATION REPLICA ON *.* TO 'rep-user'@'192.168.1.0/255.255.255.0'

レプリカサーバーの初期データセット(原始的な方法)

次にレプリカ側の初期データのセットをします。プライマリのデータが更新されないようにロックしたうえでコピー(dump)をとり、それをレプリカにインポートします。

プライマリサーバーの稼働を止められない場合は後に紹介する方法をで作業して欲しいですが、こちらの作業は基本的なものなので何をやっているかが理解しやすいと思います。

  1. テーブルのロック

    「FLUSH TABLES WITH READ LOCK;」を発行して、テーブルをロックします。これ以降すべてのテーブルがロックされますので注意してください。

    MariaDB[]> FLUSH TABLES WITH READ LOCK;
  2. バイナリログの位置を確認

    「SHOW BINLOG STATUS;」でバイナリログの位置を確認します。

    MariaDB[]> SHOW BINLOG STATUS;
    
    +------------------+----------+--------------+------------------+
    | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +------------------+----------+--------------+------------------+
    | mysql-bin.010763 | 1537532  |              |                  |
    +------------------+----------+--------------+------------------+
    

    バイナリログの設定がされていないと、何も表示されませんので注意してください。

    Fileで示されるファイル名と、Positionで示される場所(値)を記憶しておきます。この後もテーブルのロックは続けます。

  3. データ出力

    別のウインドウからプライマリサーバーにアクセスします。この時、ロック(LOCK TABLESを発行している)しているコンソール(ウインドウ)を閉じるとロックが解除されてしまいますのでそのままの状態にしておきます。

    次のコマンドで全データを出力します。このコマンドはMariaDBコンソールからではな、OSのコンソールから操作します。

    > mysqldump -u <ユーザー名> -p --all-databases --lock-all-tables>dump.data

    Debianなら/home/user/dump.data、Windowsならc:¥dump.data等わかる場所に出力してください。

    BLOBカラムを使っていたり文字化けが心配なら「--default-character-set=binary」をコマンドに追加しておくといいと思います。

  4. ロック解除

    データ出力が終わったらロックを解除します。最初に実行した方の画面で「UNLOCK TABLES;」を実行します。

    MariaDB[]> UNLOCK TABLES;

    ここまで終えたらプライマリサーバーへの MariaDB接続は切断して構いません。

  5. データコピー

    出力したdump.dataをレプリカサーバーに移動させます。

    手間なら省略できますが、大きなファイルでコピーミスはないかを確認するためにハッシュをとっておきます。

    Windowsなら

    > certutil -hashfile dump.data MD5

    Debianなら

    $ md5sum dump.data

    このコマンドを移動前と移動後の両方の環境で実行して値一致するかチェックします。一致しない場合はコピーがうまくいかなかった可能性があります。

  6. レプリカサーバーでインポート

    移動させたファイルをレプリカサーバーでインポートします。dump 時に --dafault-character-set=binary を指定して出力したらここでも指定してください。

    mysql -u root -p<dump.data
  7. 同期開始

    レプリカのMariaDBコンソールから次のコマンドを入力して、プライマリサーバーのどこのポイントから同期をとるかを指定します。

    MariaDB[]> CHANGE MASTER TO MASTER_HOST='192.168.1.1',MASTER_USER='rep-user',MASTER_PASSWORD='password',MASTER_LOG_FILE='mysql-bin000001',MASTER_LOG_POS=1;

    MASTER_HOSTにはプライマリサーバーのIPアドレスを、MASTER_USER、MASTER_PASSWORD には先ほどプライマリサーバーで作成したユーザーとそのパスワードを、MASTER_LOG_FILE、MASTER_LOG_POSには「SHOW BINLOG STATUS」実行時にメモした値をセットします。

    ちなみにサーバーのIPアドレスや、ユーザーパスワードは一度設定すれば、以降はLOG_FILEとPOSだけの指定でかまいません。

    「START REPLICA」で同期を開始させます。ちなみに同期を止めるときは「STOP REPLICA」となります。

    MariaDB[]> START REPLICA;

    稼働状況を確認するには、SHOW REPLICA STATUSコマンドをレプリカ側のMariaDBコンソールで実行します。

    MariaDB[]> SHOW REPLICA STATUS;

    長い結果が返ってきますが、「Slave_IO_Running」と「Slave_SQL_Running」の値がともに「Yes」になっていれば問題ないと思います。

    横長が見づらい場合は、行末の ; の代わりに ¥G をつけると縦型の出力になります。

    MariaDB[]> show replica status \G
    *************************** 1. row ***************************
                    Slave_IO_State: Waiting for master to send event
                       Master_Host: 172.16.1.108
                       Master_User: repl
                       Master_Port: 3306
                     Connect_Retry: 60
                   Master_Log_File: mysql-bin.010677
               Read_Master_Log_Pos: 52333893
                    Relay_Log_File: mysqld-relay-bin.000015
                     Relay_Log_Pos: 52332718
             Relay_Master_Log_File: mysql-bin.010677
                  Slave_IO_Running: Yes
                 Slave_SQL_Running: Yes
    ...
    

    もう少ししっかり確認するなら、プライマリ側で「SHOW BINLOG STATUS」で表示されたファイル名と位置、レプリカ側で「SHOW REPLICA STATUS」で表示されたプライマリサーバーのバイナリログのファイル名と位置が、一致するか確認します。

    MariaDBレプリケーション同期の確認

プライマリサーバーのデータベースを止められない場合

ストレージエンジンがInnoDBの場合、テーブルロックしないでデータを取得する方法もあります。

ただし、ストレージエンジンがMyISAMである「mysql」データーベースは対象外となります。そのため、このデータベースは一貫性を持たせるのをあきらめて後からmysql_upgaradeコマンドを利用して修正します。

それでは方法です。まず、InnoDBのデータベースを抽出します。single-transactionオプションを利用することでテーブルにロックがかからなくなります。

Bオプションで対象となるデータベースをすべてを指定します。mysqlデータベース以外の対象のデータベースをすべて記述します。

「information_schema」と「performance_schema」データベースに関しては対象としません(これらのデータベースは--all-databasesを指定しても出力されません)。testデータベースは使っていないようなら削除するか、後述する方法で同期の対象から外してください。「mysql」データベースは別途dumpしますのでこれも除外します。

master-data は同期を始めるファイル名と位置を出力するオプションです。これも併せて指定します。mastar-dataは値を与えないか 1 を設定すると、SQL文として出力され、データ取り込み時に実行されます。2とするとコメントとして書き込まれます。ここではmysql_upgradeを実行した後に同期を始めるので、2 としています。

(プライマリとレプリカの事前環境が整っていれば、master-data=1 で出力dumpデータをレプリカでインポートするだけでもいいと思います。そうすればこの後のファイル名とPOSITIONの確認と設定は不要です。)

> mysqldump -u username -p --single-transaction --databases dbname1 dbname2 --master-data=2 --quick>dump.normal.data
...
> mysqldump -u username -p mysql >dump.system.data
...

出力してレプリカサーバーにコピーしたら、まずmysqlデータベースを取り込みます。その後、mysql_upgradeを実行してmysqlデータベースに異常がないかチェックします。滅多なことはないと思いますが、mysqlデータベースが壊れてしまったら、「mysql_install_db」コマンドで初期化することができます。この時設定ファイルも初期化されてしまいますので、バクアップをとっておいてください。

> mysql -u username -p mysql <dump.system.data
...
> mysql_upgrade -u username
...

mysql_upgradeでエラーがないか、処理の過程で修正できていたら、通常のデータを取り込みます。終了したら念のためmysql_upgradeを再度実行します。

> mysql -u username -p mysql <dump.normal.data
...
> mysql_upgrade -u username
...

問題なければ、dump.normal.dataのコメントからバイナリログのファイル名と位置を取得します。Debianなら、cat dump.data | grep 'CHANGE MASTER'とするとでてきます。1行出てきたら後はCtrl+Cで、breakして構いません。(この部分のMASTERは筆者の環境では変更されていませんでした、将来変更されるかもしれません)

Windowsの場合は次のような.vbsスクリプトを使って先頭の部分だけ抽出したあとメモ帳で読み込みます。元の出力ファイルが小さければそのままメモ帳で開いてもいいです。

extract.vbs


option explicit

Dim fs
Set fs =WScript.CreateObject("Scripting.FileSystemObject")

dim APP_PATH
APP_PATH =fs.getfile(WScript.ScriptFullName).ParentFolder.path

'終了行
const ENDROW = 30

'ファイル名
constDUMP_FILE_NAME="dbdump.data"

'出力ファイル名
const OUT_FILE_NAME="dbdump.head.txt"

'エントリー
callmain()

sub main()
    dim lngCnt
    dim objFileI
    dim objFileO
    dimstrLine
    
    Set objFileI = fs.OpenTextFile(APP_PATH & "\" & DUMP_FILE_NAME,1,true)
    SetobjFileO = fs.OpenTextFile(APP_PATH & "\" & OUT_FILE_NAME,2,true)
    lngCnt = 0

    do untilobjFileI.atEndOfStream
    lngCnt = lngCnt+1
    
    strLine =objFileI.readLine
    objFileO.writeLine strLine

    if lngCnt >= ENDROWthen
        exit do
    endif
    
    loop
    
    objFileO.close
    objFileI.close
    
end sub

メモ帳を開いて上記内容をコピー&ペーストして、貼り付けます。名前を、extract.vbsにしてデスクトップに保存します。MariaDBから抽出したデータをデスクトップにコピーして名前をdbdump.dataにします。extract.vbsをダブルクリックすると、dbdump.head.txtができますのでこれをメモ帳で開いて中身を確認します。

同期するファイル名や位置がわかったら、あとは先ほどと同じように、レプリカサーバーへコピーして、取り込み、CHANGE MASTERのコマンドを入力します。

一部のテーブルだけを同期させたい場合

一部のテーブルだけを同期させたい場合は、データベース単位でバイナリログの出力の有無の指定ができます。50-server.cnfのbinlog関連のオプションでbinlog-do-db(対象を指定)やbinlog-ignore-db(非対象を指定)を使います。複数データベースを記述する際は複数行にします。

同期対象としないテーブルのバイナリログを出力すると、レプリカ側で不整合を検知して同期が止まることもありますので気を付けてください。

# 対象を指定する場合
binlog-do-db=dbname1
binlog-do-db=dbname2

# 非対象を指定する場合
binlog-ignore-db=dbname3
binlog-ignore-db=dbname4

doの方を指定すると指定しないデータベースはすべて対象外となります。ignoreを指定した場合は指定したデータベース以外は対象となります。両方を指定すると、doだけ指定した時と同じ挙動でした。ただし、出力有無の判断はカレントデータベース単位で行うようで、dbname.tablenameといったようにデータベース名を付けた更新では対象外のデータベースでもログが出力されました。

先の設定はプライマリ側でbinlogを出力しない設定ですが、場合によってはbinlogは出力させておきたいけれど、レプリケーションはさせたくないというケースがあるかもしれません。

そのような場合はレプリカ側で、レプリケーションの対象、非対称の設定をすることもできます。

レプリカの50-server.cnf

...
# 対象を指定する場合
replicate_do_db=db1
replicate_do_db=db2

# 非対象を指定する場合
replicate_ignore_db=db3
replicate_ignore_db=db4
...

また、レプリカ側ではテーブル名を指定することもできます。この時テーブル名はデータベース名で修飾します。

指定したテーブル名が更新対象となっている時に、該当のバイナリログは除外されるようになります。別のテーブルを更新するためにサブクエリ等でSELECTしている文の中に対象外としたテーブル名があってもそれは除外されません。

レプリカの50-server.cnf

...
# 対象を指定する場合
replicate_do_table=db1.tablename1
replicate_do_table=db2.tablename2

# 非対象を指定する場合
replicate_ignore_table=db3.tab
replicate_ignore_table=db4.tab
...

さらに、テーブル名の指定ではワイルドカードの使った指定の仕方もあります。ワイルド―カードはSQLのそれにならって、_ が任意の一文字 % が複数の文字列となります。エスケープ文字は \ です。

レプリカの50-server.cnf

...
# 対象を指定する場合
replicate_wild_do_table=db1.%

# 非対象を指定する場合
replicate_wild_ignore_table=db%.%tmp\_%
...

これらの設定は作業用の一時テーブルを用いる場合に便利です。プライマリ側では同名の一時テーブルは独立していますが、それがレプリカに伝えられる場合は複数セッションの処理がまとめられてしまいますので、競合し不整合を起こします。

作成される一時テーブルが恒久テーブルのデータに作用しないものなら、先の設定で一時テーブルをレプリカから除外することができます。

ちなみに、一時テーブルによるレプリケーション上の不整合の防止策としては、元の一時テーブルの名前を一意にするという方法もあります。

Row size too largeの問題

レプリカサーバーに取り込む際に、筆者の場合Row size too large (> 8126)から始まるエラーに遭遇しました。

この件については、公式ページのTroubleshooting Row Size Too Large Errors with InnoDBに載っていましたが、MariaDB 10.2.2からInnoDB Strict Modeというパラメータがデフォルト値がONで加わったの原因でした。

InnoDB Strict ModeがONの時は、新規作成や変更時にチェックを行い上限を超える可能性のあるテーブル設計の場合はエラーとなります。

ちなみにこの上限の目安はinnodb_page_sizeの約半分ぐらいだということです。

ということで、50-server-confの[mysqld]で、innodb_strict_modeをOFFにします。

[mysqld]
...
innodb_strict_mode=0
...

先の公式ページに詳細がありますが、これをONのままで対応したい場合は行フォーマットを変更するといいそうです。

レプリケーションのリセット

CHANGE MASTER を実行した際に、次のようなエラーに遭遇しました。

ERROR 1201 (HY000): Could not initialize master info structure for ''; more error messages can be found in the MariaDB error log

保持していた relay-log を誤って削除してしまい不整合が起きていたのが原因でした。

その際は reset SLAVE; を実行してレプリケーションの設定をすべて削除した後に、再び CHANGE MASTER を実行すると解決すると思います。

レプリケーションでSSL

今度は、レプリケーション用の通信を暗号化してみます。暗号化するにはCHANGE MASTERの設定を加える必要があります。

また、レプリケーションデータを暗号化するには、事前にプライマリ側のMariaDBをSSL化しておく必要があります。

レプリケーションデータの暗号化を構成する際のパターンとしては、

  1. 証明書を検証しない方法
  2. プライマリ側の証明書を検証する方法
  3. プライマリとレプリカ側両方の証明書を検証する方法

の3つあります。それぞれの方法を紹介していきますが、前述したCHANGE MASTERコマンドでSSL以外の設定は済んでいる前提です。また、CHANGE MASTERコマンド前後のSTOP REPLICAとSTART REPLICAも省略しています。

まず、一番簡単などちらの証明書も検証をしない方法です。

MariaDB []> CHANGE MASTER TO MASTER_SSL = 1;

次にプライマリ側のサーバーの証明書を検証する方法です。この場合、プライマリ側のサーバーの証明書を発行したCAの証明書が必要になるので、レプリカ側にコピーします。ここでは/etc/mysql/ca.crtにコピーしたと仮定します。

MariaDB []> CHANGE MASTER TO MASTER_SSL = 1,MASTER_SSL_CA = '/etc/mysql/ca.crt', MASTER_SSL_VERIFY_SERVER_CERT = 1;

最後にプライマリとレプリカの両方向で証明書の検証をする方法です。この場合レプリカ側にも証明書を発行する必要があります。方法はあるのかもしれまんが筆者が試してみたところ、証明書を発行するCAはプライマリと同じでないと動きませんでした(CAPATHに複数のCAの証明書を入れる方法を試してみましたがうまく動きませんでした)。

caの証明書をca.crt、レプリカ用に作成した証明書をr.crt、秘密鍵をr.keyとして、すべてレプリカ側の/etc/mysqlディレクトリに存在しているものとします。

注意が必要なのはOpenSSLを使って作成した秘密鍵(r.key)は通常rootユーザーしか読み取り権限がありませんが、MariaDBを動かしている権限で読み込めるようにする必要があります。たとえば、r.keyのオーナーをmysqlにします。

MariaDB []> CHANGE MASTER TO MASTER_SSL = 1, MASTER_SSL_CERT = '/etc/mysql/r.crt', MASTER_SSL_KEY = '/etc/mysql/r.key', MASTER_SSL_CA = '/etc/mysql/ca.crt', MASTER_SSL_VERIFY_SERVER_CERT=1;

レプリカでのエラー

レプリカでエラーを検知するとレプリケーションは停止します。先ほども少し触れましたが、プライマリ側に停止した時点からのバイナリログが残っていればエラーを解消することでレプリケーションをそのまま継続可能です。

停止状態が長引き、停止した時点からのプライマリ側のデータを補足できなくなった場合はデータの同期作業(dumpデータのコピー)からやり直さなければいけません。

レプリケーションでは下流側のデータを変更しないことは鉄則ですが、誤って行を追加してしまい後からプライマリから流れてきたデータとプライマリキーが衝突するなどといったエラーも皆無ではありません。

そのような場合 show replica status で表示される Last Error の項目ではレプリケーションを停止させる原因となったエラーを確認できます。

エラーの確認時に発生時刻を取得したいケースがあるかもしれませんが、ステータスには発生時刻は記録されていません。それを調べたい場合は、通常のMariaDBのエラーログ( /var/log/mysql/error.log等)に出力されているエラーを探します。

ちなみに、通常これらのエラーログファイルは過去の日付のものはgunzip圧縮( .gz )となっていると思います。

これらのファイルは gzip -d error.log.1.gz とするとプレーンテキストの error.1.log となり、再度.gzに戻したい(圧縮したい)場合は、gzip -n error.log.1 とします。(-nオプションはなくてもいいです。タイムスタンプと名称情報を圧縮ファイルに含めないオプションで、通常-nオプション付与の状態で保存されていると思います。)

もしエラーの原因が特定でき、問題ないと確認できたら、sql_slave_skip_counter に 1 または読み飛ばしたい数を設定して、start replica を実行することでスキップすることができます。

SET GLOBAL sql_slave_skip_counter = 1;
START REPLICA;

また、設定ファイル中の slave_skip_errorsに,で区切って複数のエラーコードを登録することができます。こうしておくと該当のエラーコードの場合は無視してレプリケーションを継続することもできます。

50-server.cnf

slave_skip_errors=1007,1008,1050,1051,1054,1060,1061,1068,1094,1146

MySQLでは全てを意味する all のほかに ddl_exist_errors (=1007,1008,1050,1051,1054,1060,1061,1068,1094,1146)がありました。MariaDBでは、ddl_exist_errors が有効かどうか微妙です。コマンドラインのオプションには載っていますが、有効値一覧には載っていません。筆者の環境では意図したように動きましたが正式サポートしているかは不明です。

いずれにしても、レプリケーションがエラーで止まるということは通常ないので、この値を設定が必要になるケースは少ないとのことでした。

ここで all や任意のコードリストを設定して読み飛ばしたエラーの数はステータス変数の slave_skipped_errors で確認することができます。

show status like '%skip%';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| Slave_skipped_errors | 0     |
+----------------------+-------+

筆者の環境ではよく、一時テーブルまわりで 1146 ( Table doesn't exist ) エラーが発生してレプリケーションが止まります。一時テーブルがなくなった後に挿入しようとするのではないかと考え、Parallel Replication の設定を次のようにしてみしました。

50-server.conf

slave_parallel_mode=none

あとで判明したのですが、筆者の場合のこの症状は先に書いたレプリカでの一時テーブルの競合が問題でしたので、レプリカ側で対象のテーブルを除外するようにして解決しました。

処理中のセッションの切断対策

大きなデータベースのdumpやimportは時間がかかります。ssh経由でそのような処理をする場合、作業中にネットワークの切断があると処理は止まってしまいます。そこでsshセッションからそれらの処理を実行する場合は、nohupを使ってバックグラウンド実行する事で、セッションが切断されても処理を継続させることができます。

このnohupのかわりにtmuxを使う方法もあります。こちらはセッションを丸ごと保存しておけますので、処理中にメッセージがでて中断するといった事象にも対応できます。

tmuxはターミナルのマルチプレクサで、ひとつのウインドウで複数のターミナルを処理できるものです。この機能のひとつにデタッチがあり、途中で接続が失われてもセッションを維持できるようになっています。

この部分の操作だけを簡単に書いておきます。詳細は先の公式ページのリンクをを参考にしてください。

  1. インストール

    aptを使ってtmuxをインストールします。

    # apt install tmux

    tmuxのコマンドの多くは省略された短い形や、覚えやすい長い形があります。ここではすべて紹介できませんが、man ページなどを参考にしてください。

  2. 起動

    「 tmux 」「 tmux new 」などで即座にセッションを開始することもできますが、ここでは-sオプションでセッション名を付けて起動させます。起動すると既存のターミナルから、tmuxのターミナルに切り替わります。

    $ tmux new -s セッション名  
    
  3. デタッチ

    ネットワーク障害なのでtmux起動中にターミナルが切断された場合そのセッションは残りますが、デタッチは意図的にセッションを残したままtmuxから抜ける方法です。detach は detach-client の省略形です。

    実行すると標準のターミナルに戻ります。

    $ tmux detach  
    
  4. ショートカットキー

    Cntrl + b キーを押すとショートカットモードになります。たとえばこの後に d を押すと、デタッチとなります。

    この操作は 「 C-b d 」といった書き方で紹介されています。

  5. tmuxセッションの確認

    既存のtmuxセッションを確認するには ls を使います。これは list-sessions の省略記法です。最初の:までがセッション名となります。セッション名を付けずに起動すると名前はインデックスとなります。

    $ tmux ls
    0: 1 windows (created Wed Mar 22 10:37:10 2022)
    test-session: 1 windows (created Wed Mar 22 10:54:48 2022)
    ...
    
  6. アタッチ

    デタッチしたtmuxセッションに再び接続します。attach は a と省略可能です。また、-tオプションを付けない場合は最後に作成したセッションにアタッチします。

    $ tmux attach -t セッション名
    
  7. tmuxセッションの終了

    tmuxセッションから、exit や logoutコマンドを実行するとそのtmuxセッションが終了します。

    $ exit

    もとの画面からセッション名を指定して削除するには tmux kill-session とします。attach時と同じように -tオプションを付けない場合は最後のセッションをクローズします。

    $ tmux kill-session -t 0

    既存のすべてのセッションをクローズしたい場合は、kill-session のかわりに kill-server とします。

tmuxはユーザー権限で起動できますが、一度管理者権限で作成したセッション一覧をユーザー権限で見ようとするとエラーになるので注意してください。

筆者紹介


自分の写真
がーふぁ、とか、ふぃんてっく、とか世の中すっかりハイテクになってしまいました。プログラムのコーディングに触れることもある筆者ですが、自分の作業は硯と筆で文字をかいているみたいな古臭いものだと思っています。 今やこんな風にブログを書くことすらAIにとって代わられそうなほど技術は進んでいます。 生活やビジネスでPCを活用しようとするとき、そんな第一線の技術と比べてしまうとやる気が失せてしまいがちですが、おいしいお惣菜をネットで注文できる時代でも、手作りの味はすたれていません。 提示されたもの(アプリ)に自分を合わせるのでなく、自分の活動にあったアプリを作る。それがPC活用の基本なんじゃなかと思います。 そんな意見に同調していただける方向けにLinuxのDebianOSをはじめとした基本無料のアプリの使い方を紹介できたらなと考えています。

広告