恥は/dev/nullへ by 初心者

プログラミング初心者がのろのろと学んだことをつづっています♪

vim-plugの導入

DebianにRust環境を構築しました。これに合わせてvimにもRust環境を作ることにしたのですが、そのついでに、「とても簡単で便利」と良く言われるプラグインマネージャ、vim-plugを使うことにしました。

ただ、しょうもないことで少し時間を取ったので、また同じ轍を踏まないように備忘録を残しておくことにします。

 

 

環境

VirtualBox 6.1.18

Debian GNU Linux 10 (buster)

vim 8.1 (apt install でDebianリポジトリからインストール)

 

 

vim-plugの入手先

https://github.com/junegunn/vim-plug

 

 

インストール手順

(1)ターミナルを開いてcurlコマンドを実行します。
curl -fLo ~/.vim/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

 

すると、ホームディレクトリに .vim ディレクトリが出来上がります。

階層構造は以下の通り。

~/.vim/autoload/plug.vim

(2)ついでに、pluggedディレクトリを作成します。
mkdir ~/.vim/plugged

もしかしたら、後の作業のPlugInstallで自動作成される可能性もありますが、良く分からなかったので手動で作っておきました。

 

(3)ホームディレクトリにある.vimrcファイルにvim-plugの設定を記述します。
call plug#begin('~/.vim/plugged')
    Plug 'https://github.com/cohama/lexima.vim'
    Plug 'Yggdroot/indentLine'
call plug#end()

この例では、leximaとindentLineというプラグインを記述しています。
3行目の例のように https://github.com/ を省略して記述しても問題ありません。

 

(4) .vimrcファイルの編集が終わったら、一度vimを終了します。

 

(5)再びvimを起動し、PlugInstallコマンドを実行します。
:PlugInstall

 

これで、設定したプラグインgithubからPCに取り込まれるはずなのですが・・・。
ここで一度ストップしました。画面には「E492: Not an editor command」というメッセージが表示されました。:PlugInstall ができないのです。

 

PlugInstallを実行できない時の解決策

ネット検索をしたところ、「gitが入ってないのでは?」という意見が書かれていたので、gitをインストールしました。

su -
apt update
apt upgrade
apt install git

 

ここで一つ注意することがあります。

apt install git-all     # ダメな例

としてはいけません!(これで自分は時間を無駄にしました)

 

gitをインストールしてからvimを起動して、

:PlugInstall

と入力しました。

今度は無事に実行されプラグインがインストールされました。

 

プラグインの保存場所

.vimrcに記述した内容の通りなのですが、以下のディレクトリにプラグインが保存されます。

~/.vim/plugged

 

個々のプラグインの設定

leximaの方は特に設定しなくても勝手に括弧を補完してくれますが、indentLineの方は設定が必要です。.vimrcに以下の記述を追加しました。

"-------------------------------------------------
" インデントを可視化するプラグイン indentLine
"-------------------------------------------------
let g:indentLine_color_term = 111
let g:indentLine_color_gui = '#708090'
let g:indentLine_char = '¦' "use ¦, ┆ or │

 

 apt install git-all の顛末

git-allをインストールするaptを実行したところ、インストール途中でGUI画面が落ちて、黒い画面になりました。そこで、CTRL + ALT + F1 でコンソールに切り替えて

shutdown -r now

で再起動をかけたのですが、起動プロセスの途中で止まってしまいました。

原因が「apt install git-all」なのか、それ以外なのか分からなかったのでもう一度「apt install git-all」を実行したらやはりGUI画面が落ちて黒い画面になりました。git-allはインストールしない方が良さそうです。

 

 

robocopyのログを読みやすくする

 問題点

 バッチファイルにrobocopyコマンドを記述してデータのバックアップを取っているのですが、気になることが1つありました。

ログファイルの最後に出力される「合計」などの部分がズレて読みにくいんですよね^^;。

 

試しに「ピクチャ」フォルダをrobocopyでバックアップしてみます。

 

robocopy C:\Users\hogehoge\Pictures\ D:\Backup\Pictures\ /MIR /R:3 /W:3 /NP /NDL /LOG:D:\Backup\robocopy_Pictures.log

を実行して出力されたログファイルを見ると、以下のように、下段にある「合計」等の各列(赤文字にした部分)が読みにくいです。

 

-------------------------------------------------------------------------------
   ROBOCOPY     ::     Windows の堅牢性の高いファイル コピー                              
-------------------------------------------------------------------------------

  開始: 2021年3月6日 6:29:42
   コピー元 : C:\Users\hogehoge\Pictures\
     コピー先 : D:\Backup\Pictures\

    ファイル: *.*
	    
  オプション: *.* /NDL /S /E /DCOPY:DA /COPY:DAT /PURGE /MIR /NP /R:3 /W:3 

------------------------------------------------------------------------------

	  *EXTRA File 		   14565	D:\Backup\Pictures\あとで削除.png

------------------------------------------------------------------------------

                  合計     コピー済み      スキップ       不一致        失敗    Extras
   ディレクトリ:         3         0         3         0         0         0
     ファイル:        25         0        25         0         0         1
      バイト:    2.09 m         0    2.09 m         0         0    14.2 k
       時刻:   0:00:00   0:00:00                       0:00:00   0:00:00
   終了: 2021年3月6日 6:29:42

 

 

次の問題点

 ネット情報によると、ログファイルを英語表記で出力すれば上述のズレが生じないそうです。やることはrobocopyを実行する前に、以下のコマンドを実行するだけです。 

chcp 65001

 これで、コマンドプロンプトで使用される文字コードが「UTF-8」になります。なお、65001はコードページと呼ばれるもので、以下のMicrosoftのページに記載されています。

 https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers

 

chcp 65001
robocopy C:\Users\hogehoge\Pictures\ D:\Backup\Pictures\ /MIR /R:3 /W:3 /NP /NDL /LOG:D:\Backup\robocopy_Pictures.log

を実行して出力されたログファイルは以下のとおりです。

 

-------------------------------------------------------------------------------
   ROBOCOPY     ::     Robust File Copy for Windows                              
-------------------------------------------------------------------------------

  Started : 202136 6:28:19
   Source : C:\Users\hogehoge\Pictures\
     Dest : D:\Backup\Pictures\

    Files : *.*
	    
  Options : *.* /NDL /S /E /DCOPY:DA /COPY:DAT /PURGE /MIR /NP /R:3 /W:3 

------------------------------------------------------------------------------

	  *EXTRA File 		   14565	D:\Backup\Pictures\後ほど消す.png
	    New File  		   14565	C:\Users\hogehoge\Pictures\あとで削除.png

------------------------------------------------------------------------------

               Total    Copied   Skipped  Mismatch    FAILED    Extras
    Dirs :         3         0         3         0         0         0
   Files :        26         1        25         0         0         1
   Bytes :    2.11 m    14.2 k    2.09 m         0         0    14.2 k
   Times :   0:00:00   0:00:00                       0:00:00   0:00:00


   Speed :             3641250 Bytes/sec.
   Speed :             208.353 MegaBytes/min.
   Ended : 202136 6:28:19

 

 確かにズレは生じていません。しかし、日付の表記が分かりにくいですね。2021年3月6日が「202136」と表示されています。

 

解決策

 /LOGオプションの代わりに/UNILOGオプションを使うと、日付の表記が「2021年3月6日」になりました。というわけで、以下の手順を踏むことにしました。

 

(1)robocopyを実行する前に「chcp 65001」を実行する。

(2) /LOG  ではなく  /UNILOG  を使用する。

 

chcp 65001
robocopy C:\Users\hogehoge\Pictures\ D:\Backup\Pictures\ /MIR /R:3 /W:3 /NP /NDL /UNILOG:D:\Backup\robocopy_Pictures.log

を実行して出力されたログは以下のとおりです。ズレは解消され、かつ、日付の表記も分かりやすいです。

 

-------------------------------------------------------------------------------
   ROBOCOPY     ::     Robust File Copy for Windows                              
-------------------------------------------------------------------------------

  Started : 2021年3月6日 6:23:42
   Source : C:\Users\hogehoge\Pictures\
     Dest : D:\Backup\Pictures\

    Files : *.*
	    
  Options : *.* /NDL /S /E /DCOPY:DA /COPY:DAT /PURGE /MIR /NP /R:3 /W:3 

------------------------------------------------------------------------------

	  *EXTRA File 		   14565	D:\Backup\Pictures\あとで消す.png
	    New File  		   14565	C:\Users\hogehoge\Pictures\後ほど消す.png

------------------------------------------------------------------------------

               Total    Copied   Skipped  Mismatch    FAILED    Extras
    Dirs :         3         0         3         0         0         0
   Files :        26         1        25         0         0         1
   Bytes :    2.11 m    14.2 k    2.09 m         0         0    14.2 k
   Times :   0:00:00   0:00:00                       0:00:00   0:00:00


   Speed :            14565000 Bytes/sec.
   Speed :             833.415 MegaBytes/min.
   Ended : 2021年3月6日 6:23:42

延長されない水平線を描画するボタン

MT4の水平線ボタンを使用して水平線を作成した場合、横方向に延長されて(チャートの端から端まで)描画されます。しかし、延長して描画したくない場合もあります。

そこで、トレンドラインを水平線代わりに使用することにしました。トレンドラインなら、ラインを「延長して描画することも、延長しないで描画することも」できるからです。

 しかし、マウス操作でトレンドラインをきっちり水平にしようとしても多少ブレてしまうことがあります。そこで、水平なトレンドラインを描画するボタンを作成しました。

 (作成といっても、このブログにアップされている「MT4用水平線描画ボタン」を少し改造しただけですが^^;。)

  

スクリーンショット

f:id:philojuan:20210224153438p:plain

 

使い方

(1)画面上部に設置されている FlatTLボタンをクリックします。
(2)チャート上の2つの地点をクリックします。

以上の操作で水平なトレンドラインが描画されます。

トレンドラインの描画位置(高さ・Y軸位置)は、最初にクリックした地点の高さとなります。一方、トレンドラインの幅(長さ)は、1回目のクリック地点と2回目のクリック地点の間となります。

 

備考

以下のコードでは、OBJPROP_SELECTEDtrueになっているので、ラインが作成された時点で「選択可能」状態になります。

 

コード

//------------------------------------------------------------------
//
// FileName: FlatTrendLineButton.mq4
//
// Feature : This indicator sets a button to draw a HORIZONTAL trend line.
//
// Usage   : After clicking the button, click two separate points on the chart.
//           
//------------------------------------------------------------------
#property copyright "Copyright 2021. PHILOJUAN"
#property link      "https://uhoho.hatenablog.jp/"
#property strict
#property indicator_chart_window

enum OnOff {OFF, ON};                    // enumでOnOff型を定義

//--------------------------------------------------------------------
// グローバル変数 (パラメーター設定の対象とするもの)
//--------------------------------------------------------------------
input OnOff deleteAtDeInit = OFF;        // インディケーター除去時にトレンドラインを全て削除

// ボタンのパラメーター
input int buttonXdis1    = 390;          // ボタンの表示位置(X軸)
input int buttonYdis1    =   4;          // ボタンの表示位置(Y軸)
input color tlColor1 = clrGold;          // 水平トレンドラインの色
ENUM_LINE_STYLE tlStyle1 = STYLE_DASH;   // 線種はダッシュ型
int  tlWidth1  = 1;                      // 太さは1

//--------------------------------------------------------------------
// グローバル変数 (パラメーター設定の対象にしないもの)
//--------------------------------------------------------------------
// CHARTEVENT_CLICK()内の[UTSUWA] という部分で使用する変数
// 初期化しているがtlColor1等の値を代入するための器に過ぎない
color TLcolor = clrAqua;     // 色
int   TLstyle = STYLE_SOLID; // 線種
int   TLwidth = 1;           // 太さ

// クリックしたXY座標を時刻と価格に変換して格納するための変数
// (step == 2 と step == 3 で使う)
datetime time1 =  0;  // 初期化の仕方が不思議だが、ChartXYToTimePriceのヘルプのとおり
double price1 = 0.0;
datetime time2 =  0;
double price2 = 0.0;
int window = 0;       // 0 はメインチャートを指す(サブウィンドウではない)

// その他
int step        = 0;             // 処理のステップ管理に使う変数
int numTL       = 0;             // 作成したトレンドラインの数
string baseName = "uhoTreLine";  // オブジェクトのベース名
string objName  = "";            // オブジェクト名に使う変数
string clickedButton = "";       // クリックされたボタン名を格納する変数

//+------------------------------------------------------------------
//| Custom indicator initialization function
//+------------------------------------------------------------------
int OnInit()
{
    MakeButton("TLbutton01", buttonXdis1, buttonYdis1, tlColor1, "FlatTL");

    return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
    return(rates_total);
}

//+------------------------------------------------------------------+
//| インジケーター除去時の処理
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    // オブジェクト名の先頭を使用してまとめて消去
    ObjectsDeleteAll(0, "TLbutton0");
// 今後、TLbutton01、 TLbutton02・・・と複数のボタンを設置する予定なので
// ObjectsDeleteAllを使用。 if(deleteAtDeInit) ObjectsDeleteAll(0, baseName); } //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { // オブジェクトクリック時 if(id == CHARTEVENT_OBJECT_CLICK) { if(sparam == "TLbutton01") { if(!step) step = 1; TLcolor = tlColor1; TLstyle = tlStyle1; TLwidth = tlWidth1; clickedButton = sparam; } } // マウスクリック時 if(id == CHARTEVENT_CLICK) { // 1回目のクリック時(ボタンをクリックした時) if(step == 1) step = 2; // このstep == 1 の段階が無いと、ボタンをクリックしたのと同時に // 次の処理が実行されてしまう。 // 2回目のクリック時(1つ目の地点をクリックした時) else if(step == 2) { // クリックしたXY座標を取得 int x1 = (int)lparam; int y1 = (int)dparam; // 上述の2行については ChartXYToTimePrice関数のヘルプに同様の例文がある // https://docs.mql4.com/chart_operations/chartxytotimeprice // クリックした地点の座標を時間と価格に変換してtime1とprice1に代入 if(!ChartXYToTimePrice(0, x1, y1, window, time1, price1)) { Print("ChartXYToTimePrice error ", GetLastError()); // エラーメッセージを表示 } step = 3; } // 3回目のクリック時(2つ目の地点をクリックした時) else if(step == 3) { // クリックしたXY座標を取得 int x2 = (int)lparam; int y2 = (int)dparam; // クリックした地点の座標を時間と価格に変換してtime2とprice2に代入 if(!ChartXYToTimePrice(0, x2, y2, window, time2, price2)) { Print("ChartXYToTimePrice error ", GetLastError()); } // オブジェクト名の最後に番号を付ける objName = baseName + IntegerToString(numTL); // 名前の例 // 最初のオブジェクト uhoTreLine0 // 2番目のオブジェクト uhoTreLine1 // 3番目のオブジェクト uhoTreLine2 // 既に同じ名前のオブジェクトがあった場合への対応 for(int i = 0; i < ObjectsTotal(); i++) { if(ObjectName(i) == objName) { numTL++; objName = baseName + IntegerToString(numTL); } } // 説明 // 既にuhoTreLine0 というオブジェクトがあった場合は // uhoTreLine1というオブジェクトを作る // [UTSUWA] // クリック位置に水平なトレンドラインを描画(1度しか登場しないので、自作関数にはせず) ObjectCreate( 0, objName, OBJ_TREND, 0, time1, price1, time2, price1); // 水平にするためにprice1を2回使用 ObjectSetInteger(0, objName, OBJPROP_COLOR, TLcolor); ObjectSetInteger(0, objName, OBJPROP_STYLE, TLstyle); ObjectSetInteger(0, objName, OBJPROP_WIDTH, TLwidth); ObjectSetInteger(0, objName, OBJPROP_BACK, false); ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, true); ObjectSetInteger(0, objName, OBJPROP_SELECTED, true); // ライン作成後、選択状態にする ObjectSetInteger(0, objName, OBJPROP_HIDDEN, false); ObjectSetInteger(0, objName, OBJPROP_ZORDER, 0); ObjectSetInteger(0, objName, OBJPROP_RAY_RIGHT, false); // ラインを延長しない step = 0; ObjectSet(clickedButton, OBJPROP_STATE, false); } // else if(step == 3) ここまで } } void MakeButton(string buttonName, // オブジェクト名 int xDis, // X座標 int yDis, // Y座標 color bgColor, // ボタンの背景色 string text // ボタンに表示するテキスト ) { ObjectCreate( 0, buttonName, OBJ_BUTTON , 0, 0, 0); ObjectSetInteger(0, buttonName, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, buttonName, OBJPROP_XDISTANCE, xDis); ObjectSetInteger(0, buttonName, OBJPROP_YDISTANCE, yDis); ObjectSetInteger(0, buttonName, OBJPROP_XSIZE, 40); ObjectSetInteger(0, buttonName, OBJPROP_YSIZE, 18); ObjectSetInteger(0, buttonName, OBJPROP_COLOR, clrBlack); // ボタン内の文字の色 ObjectSetInteger(0, buttonName, OBJPROP_BGCOLOR, bgColor); ObjectSetInteger(0, buttonName, OBJPROP_BORDER_COLOR, clrGray); ObjectSetInteger(0, buttonName, OBJPROP_BORDER_TYPE, BORDER_RAISED); ObjectSetInteger(0, buttonName, OBJPROP_BACK, false); ObjectSetInteger(0, buttonName, OBJPROP_STATE, false); ObjectSetInteger(0, buttonName, OBJPROP_HIDDEN, true); ObjectSetInteger(0, buttonName, OBJPROP_ZORDER, 1); ObjectSetInteger(0, buttonName, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, buttonName, OBJPROP_SELECTED, false); ObjectSetInteger(0, buttonName, OBJPROP_FONTSIZE, 7); ObjectSetString( 0, buttonName, OBJPROP_FONT, "HackGen"); ObjectSetString( 0, buttonName, OBJPROP_TEXT, text); }

 

Linuxつまみ食いメモ

ZorinOS

本家Ubuntuよりも軽いとネットに書かれていたのでZorinOSをインストールしてみたのですが、そんなに軽いとは感じませんでした。ただ、インストール直後に日本語入力できますし、使っていて不便な点は特になし。よくできているなあと思いました。

 

Xubuntu

軽量ということではLubuntuとXubuntuに定評があります。この2つのうちLubuntuの方が軽いという記事を見かける一方で、Xubuntuの方が安定しているという記事も目にしたので、Xubuntuをインストールしてみました。

自分の環境ではZorinOSよりも動きが軽くて良い感じです。また、ZorinOSと同様に、使いやすく、インストール直後これといった設定をせずに日本語入力ができました。

 

余談(Google Chrome

今のところ、GoogleのサイトにあるLinux用のChromeは .deb形式と .rpm形式の2種類です。Debian系やRedHat系以外のLinuxを使う場合はChromiumを使うしかないのでしょうか??(Arch Linuxでは有志作成のChromeをAURから取ってこられるみたいですが。)

Debianメモ(3) automatic package

  

 この記事の情報源

buster用のDebian Administrator's Handbookを元にして、この記事を書いています。
https://debian-handbook.info/

本記事では、以下「buster用ハンドブック」と記述します。

 

 

automatic packageとは?

依存関係を満たすためだけにインストールされたパッケージのことを automatic package と呼びます。

 

 

automatic packageを除去するコマンド 

あるパッケージを削除した後、もう必要のない automatic package を除去するには次のコマンド(どちらか1つ)を使います。

apt autoremove
apt-get autoremove

 

busterハンドブックによると、aptitudeは automatic package を見つけると自動的に削除するので、aptitudeには上記コマンドが存在しないそうです。

 

 

automatic package を指定するコマンド

必要なくなった時、自動的に削除されるように、自分が直接必要としていないパッケージを automatic としてマークしておきましょうとbusterハンドブックに書かれていますが、ドライブの容量がひっ迫していなければ自分はやらなさそうな気がしなくもありません(ぼそっ)。

 

パッケージを automatic としてマークするには以下のコマンドがあります(どちらか1つ)。

apt-mark auto パッケージ名
aptitude markauto パッケージ名

 

なお、反対のコマンドは以下のとおりです(どちらか1つ)。

apt-mark manual パッケージ名
aptitude unmarkauto パッケージ名

 

 

インストールされた理由を調べる(aptitude why)

ある automatic package が何故システムに存在するのか調べるには、aptitude why コマンドを使います。なお、aptやapt-getにはこれに相当するコマンドが無いようです。

(busterハンドブックに載っていた使用例)

$ aptitude why python-debian

 

(実行結果)

i aptitude Suggests apt-xapian-index
p apt-xapian-index Depends python-debian (>= 0.1.14)

 

 

deborphanとdebfoster

不要なパッケージを除去するのに使えるコマンドとして、deborphan、debfosterというものがあるようです。どちらも使ったことが無いので、busterハンドブックやmanページを斜め読みしてアバウトに理解したことをメモしておきます。

 

deborphanは libsセクションや oldlibsセクションを調べて、他のパッケージが依存していないパッケージを探してくれるようです。ちなみに、-d オプションを付けて実行すると、インストールされている全てのパッケージと依存しているパッケージを表示してくれます。

 

debfosterは(依存関係を満たすために自動的にインストールされたパッケージではなく)ユーザーが直接要求してインストールしたパッケージの一覧を保持しています。debfosterがこの一覧に記録していないパッケージを見つけた場合、もしくは、かつては依存関係を形成していたものの今はもう依存関係が無くなり孤立していると認識した場合、このパッケージをどうするかユーザーに尋ねてくるようです。

 

Debianメモ(2) パッケージやシステムのupgradeとログファイル

upgrade系コマンドについて、Debian Administrator's Handbookを読みました(ただ、目新しい知識は余りありませんでした^^;。distributionを指定してupgradeする方法くらいだったような気がします。)。

 

 

この記事の情報源

buster用のDebian Administrator's Handbookを元にして、この記事を書いています。
https://debian-handbook.info/

 

本記事では、以下「buster用ハンドブック」と記述します。

 

 

パッケージのアップデート

先にapt updateを行った上で、以下のいずれかのコマンドを実行します。

apt upgrade
apt-get upgrade
aptitude safe-upgrade

このうち、(aptやaptitudeに比べると)apt-getはやや厳しく、事前にインストールされていないパッケージのインストールを拒む、とbusterハンドブックに書かれています。aptやaptitudeは、必要ならマシン上に存在しないパッケージもインストールするということでしょうか・・・?

この点は他のサイトを後日調べてみることにします。

 

distributionを指定してアップグレード

アップグレードされたパッケージを探す時に、特定のdistribution(stable版、unstable版、buster、stretchなど)を指定するには、aptに対して -t オプションか --target-releaseオプションを使用します。

apt -t stable upgrade

 

毎回指定するのが面倒な場合は、/etc/apt/apt.conf.d/local に以下のように記述します。

APT::Default-Release "stable"

 

システム全体のアップグレード

システム全体のアップグレードには以下のいずれかのコマンドを使います。

apt full-upgrade
aptitude full-upgrade
apt-get dist-upgrade

 

apt や aptitude の場合は full-upgrade を使いますが、以下のようにdist-upgrade を使うこともできるそうです。

apt dist-upgrade
aptitude dist-upgrade

 

ログファイル

apt等でアップグレードした内容は以下のログファイルにあります。

/var/log/apt/history.log
/var/log/apt/term.log

 

一方、dpkgのログは次のファイルに記述されています。

/var/log/dpkg.log

 

APTの設定ファイル等

/etc/apt/apt.conf.d/ ディレクトリ、または /etc/apt/apt.conf ファイルに指示を記述することでAPTの挙動を設定することができますが、busterハンドブックには余り詳しいことが書かれておらず、「man apt.conf」を読みましょうとのことでした。
実際、それが一番良いと思います。

 

.d で終わるディレクト

名前が .d で終わるディレクトリには、複数の設定ファイルが入っています。

たとえば、/etc/apt/apt.conf.d/ にはAPTに対する指示が記述されたファイルがあります。


APTはそれらのファイルをアルファベット順に読み込むため、最初の方でなされた指示を最後の指示によって変更することができます。busterハンドブックには「この仕組みが、マシンの管理者やパッケージのメンテナーに柔軟性をもたらす。」と書かれています。

 

外部スクリプトが .dディレクトリにある設定ファイルを結合して設定ファイルを自動生成するケースがあるようです。この場合の注意点について、busterハンドブックに次のように書かれています。

 

Depending on the application, the .d directory is used directly or managed by an
external script which will concatenate all the files to create the configuration file
itself. It is important to execute the script after any change in that directory so
that the most recent modifications are taken into account. In the same way, it is
important not to work directly in the configuration file created automatically, since
everything would be lost at the next execution of the script.

 

(テキトーな訳)
アプリケーションによっては .d ディレクトリを外部スクリプトが直接利用したり管理したりします。このスクリプトは全てのファイルを結合して設定ファイルを作り出します。
.d ディレクトリに何か変更を加えた後は、直近の変更を反映させるために、このスクリプトを実行することが重要です。
また、外部スクリプトにより自動生成された設定ファイルを直接変更してはいけません。次にスクリプトを実行した時に変更内容が全て失われてしまうからです。

 

/usr/share/doc/パッケージ名/README.Debian

当たり前ですが、/usr/share/doc/パッケージ名/README.Debian を読むのは大切ですね。busterハンドブックに次の記述があります。

 

Without a .d directory, it is impossible for an external package to change the settings of a program without modifying its configuration file. Instead it must invite the user to do it themselves and lists the operations to be done in the file
/usr/share/doc/package/README.Debian.

 

(テキトーな訳)
.d ディレクトリが無い場合、設定ファイルを変更せずに外部パッケージがプログラムの設定を変更することはできません。代わりに、ユーザーが設定を変更するように案内し、/usr/share/doc/パッケージ名/README.Debian に必要な作業内容を一通り記述しておく必要があります。

Debianメモ(1) パッケージのインストールや削除、キャッシュの掃除ほか by APT

普段、何気なくapt-get install等を使っていますが、ちゃんとマニュアルを読んだことがなかったのでDebian Administrator's Handbookを読んで知識を整理してみました。

 

 

この記事の情報源

buster用のDebian Administrator's Handbookを元にして、この記事を書いています。
https://debian-handbook.info/

 

本記事では、以下「buster用ハンドブック」と記述します。

なお、本記事に登場するbuster用ハンドブックのページ番号は、英語版のbuster用ハンドブックに対応しています。

 

 APTという表現

APTは Advanced Package Tool の略語で、パッケージの管理システム全体を指す言葉です。aptコマンドはその一部です。
本記事では、aptコマンドと区別するために、大文字でAPTと表記しています。

 

余談ですが、Debian Wikiを見たら、APTに含まれる各種ツールが以下のページに載っていました。

PackageManagementTools - Debian Wiki 

 

 apt-getとapt

buster用ハンドブックによると、APTプロジェクトにおける最初のフロントエンドがapt-getで、2番目のフロントエンドがaptです。aptは対話型の利用に向けて改良されている一方、apt-getはパッケージのインストール作業をシェルスクリプト等で行うシーンで好まれるそうです。

なお、buster用ハンドブックはaptを推奨しています。

 

よく使うコマンド

apt update (パッケージの一覧をアップデート)
apt install   (パッケージをインストール)
apt remove (設定ファイルを残してパッケージを削除)
apt-get clean または apt-get autoclean (キャッシュディレクトリを掃除)

 

まずはパッケージの一覧をアップデート

新たにパッケージをインストールする前に

apt update

 を実行し、利用できるパッケージの一覧をアップデートします。
buter用ハンドブックによると、Packages, Sources, Translation-language-codeなどのファイルをリポジトリからダウンロードしているようです。

 

パッケージのインストールと削除

パッケージをインストールするには

apt install パッケージ名

 とします。自動的に、依存関係を満たすように必要なファイル一式をインストールします。

(使用例)

apt install vim

この使用例では vim をインストールしています。

 

パッケージを削除するには、

apt remove パッケージ名

とします。自動的に、削除するパッケージが依存していたパッケージも削除します。
apt purgeと異なり、設定ファイルは削除されずに残ります。

(使用例)

apt remove vim

 

設定ファイルも含めてパッケージを削除する場合は

apt purge パッケージ名

とします。apt removeと異なり、設定ファイルも含めて完全にアンインストールされます。

 (使用例)

apt purge vim


あるパッケージをインストールするついでに、別のパッケージを削除したい場合

apt install package1 package2-

 とすることで、package1がインストールされ、package2が削除されます。

なお、同じことをするのに、以下のようにすることもできます。

apt remove package1+ package2

 この2つの例にあるとおり、パッケージ名の末尾に「+」を付けたものがインストールされ、「-」を付けたものが削除されます。

 

【地味に大切】キャッシュ用ディレクトリをお掃除する

(buster用ハンドブック 119ページ)
APTはダウンロードしたdebファイルのコピーを /var/cache/apt/archives/ に保存しています。そのため頻繁にアップデートがあった場合、このディレクトリが肥大化します。そこで、定期的にこのディレクトリを掃除する必要があります。

この目的に使われるコマンドとして、apt-get cleanapt-get autocleanがあります。

 

apt-get clean

 /var/cache/apt/archives/ディレクトリを丸ごと空っぽにします。

 

apt-get autoclean

 もうダウンロードすることができなくなったパッケージ(リポジトリから無くなったパッケージ)だけを/var/cache/apt/archives/から削除します。

 

インストール済みのパッケージを再インストールする方法

buster用ハンドブックの118ページに、既にインストールされているパッケージを再インストールする方法が書かれています。

たとえば、パッケージのファイルを修正した結果、システムが上手く動かなくなったとします。こんな時、壊れたファイルを修復するためにパッケージを再インストールしたいところです。しかし、パッケージが既にインストールされているため、システムはパッケージのインストールを拒否します。

 

このような場面で、aptコマンドに --reinstall オプションを使います。
以下の例ではpostfixのパッケージを再インストールしています。

apt --reinstall install postfix

 

なお、aptitudeを使う場合は次のようになります。

aptitude reinstall postfix

 

パッケージのバージョンを指定してインストールする方法

(buster用ハンドブックの119ページ)
sources.listファイル内で複数のディストリビューション(stable版、testing版、unstable版など)を参照するように設定されていれば、aptコマンドに対してインストールしたいバージョンを指定することができます。

 

apt install パッケージ名=バージョン

 という形式も使えるものの、通常は以下の形式が好まれるそうです。

apt install パッケージ名/ディストリビューション

 

たとえば、unstable版に含まれるspamassassinパッケージをインストールする場合、次のようになります。

apt install spamassassin/unstable

 

複数台のマシンに同じパッケージ群をインストールする方法

あるマシンにインストールされているのと同じパッケージ構成を他のマシンにインストールする方法が、buster用ハンドブックの117~118ページに書かれています。

 

最初に、既に各種パッケージのインストールが終わっているマシンで

dpkg --get-selections > pkg-list

を実行して、パッケージの一覧をpkg-listファイルに書き出します。

 

書き出したファイルをこれからパッケージをインストールしたいマシンに保存して、以下のコマンドを実行します(buster用ハンドブックからそのままコピペしました)。

## Update dpkg’s database of known packages
avail='mktemp'
apt-cache dumpavail > "$avail"
dpkg --merge-avail "$avail"
rm -f "$avail"

## Update dpkg’s selections
dpkg --set-selections < pkg-list

## Ask apt-get to install the selected packages
apt-get dselect-upgrade

 

参考までに、manに書かれていた各コマンドの意味は次のとおりです。

apt-cache dumpavail

利用可能なパッケージの一覧を標準出力に表示します。

 

dpkg --merge-avail ファイル名

古い情報を(引数として指定した)パッケージファイルの情報と結合します。

 

dpkg --set-selections ファイル名

引数として指定したファイルの内容をセットします。

 

buster用ハンドブックによると、最初の方のコマンド(apt-get dselect-upgrade以外のコマンド)は、dpkgデータベースにある利用可能なパッケージの一覧を記録するものだそうです。 

あとは、apt-get dselect-upgradeが必要なことをやってくれますが、aptitudeにはこれに相当するコマンドが無いそうです。