CHUWI HeroBoxにLinuxディストリビューションをインストール
前口上
小型で気軽に使えるLinuxサーバが欲しくてCHUWI HeroBoxをゲット。 試行錯誤をしまくって、何とかモノになったので覚え書き。
スペックとかレビューは色々な人が紹介しているので省略。 このPCは元々256GBのSSDを内蔵しているけど、手元に512GBの2.5インチSSDが余っていたのでこれを増設。
Linuxディストリビューションの選択
結局、Ubuntu Server 20.10に落ち着いた。 他のインストール候補はRed Hat Enterprise Linux 8とCentOS 8。これら以外にFedoraとかCentOS 8 Streamを入れたけどすぐに消した。一時、RHEL8で使っていたのだけど、Docker絡みとPostgreSQL絡みでRHELは諦めた。
HeroBoxへのLinuxのインストール
起動とインストール
LinuxのインストールはインストールイメージをダウンロードしてRufusでUSBメモリに書込み。 USBメモリを前面右側のUSB3.0ポートに刺して起動。F7を連打すればブートメディアを選択できる。RHELの場合はブート可能なパーティションが2つあるので第2パーティションからブート。オフラインインストールとなる。オフラインインストール後にアクティベーションを行えばパッケージの更新が出来る。 第1パーティションはネットワークインストール用。最初はこれを選択したもののインストール中にRHELのアクティベーションが上手く行かなかったので挫折しかかった。
Ubuntu Server 20.10の場合はインストーラーの指示に従えばOK。 インストール先は512GBのSSDを選択。LVMでフォーマットするのでインストール後に256GB側を拡張して1つのファイルシステムにする。 RHELはインストール時に2台のSSDを1つの論理パーティションにしてインストールできた。
インストール後のディスクの構成はこんな感じ。
# df -hP Filesystem Size Used Avail Use% Mounted on tmpfs 778M 1.3M 777M 1% /run /dev/mapper/ubuntu--vg-ubuntu--lv 456G 6.3G 427G 2% / tmpfs 3.8G 0 3.8G 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 4.0M 0 4.0M 0% /sys/fs/cgroup /dev/sda2 976M 112M 798M 13% /boot /dev/sda1 511M 7.9M 504M 2% /boot/efi tmpfs 778M 4.0K 778M 1% /run/user/1000
既存のファイルシステムに空きドライブを追加して1つのファイルシステムにする
物理ディスクが複数ある場合、これを1つに統合するのは信頼性が低下するので宜しくないけど、運用の柔軟性をとってRAID0構成に。 以下の手順で既存の/dev/sdaに/dev/sdbを追加して1つのファイルシステムにした。
パーティション作成
パーティションを作成する前にvgdisplay
で既存のボリュームグループの状態を確認する。
# vgdisplay --- Volume group --- VG Name ubuntu-vg System ID Format lvm2 Metadata Areas 1 Metadata Sequence No 2 VG Access read/write VG Status resizable MAX LV 0 Cur LV 1 Open LV 1 Max PV 0 Cur PV 1 Act PV 1 VG Size <464.26 GiB PE Size 4.00 MiB Total PE 118850 Alloc PE / Size 118850 / <464.26 GiB Free PE / Size 0 / 0 VG UUID eljjjs-eqqz-wes6-fkSC-SQUQ-P8wI-P4KETF
ボリュームグループはインストール時に選択した512GBのSSD(/dev/sda)に作成されている。これに、空である256GB側(/dev/sdb)を追加する。
まずは、gdisk
で/dev/sdbでパーティションを編集
# gdisk /dev/sdb GPT fdisk (gdisk) version 1.0.5
pコマンドでパーティションの状態を確認。
Command (? for help): p Disk /dev/sdb: 500118192 sectors, 238.5 GiB Model: KINGSTON RBUSNS8 Sector size (logical/physical): 512/512 bytes Disk identifier (GUID): 5394AF49-2144-4AB8-9D79-BBFB489DCCBC Partition table holds up to 128 entries Main partition table begins at sector 2 and ends at sector 33 First usable sector is 34, last usable sector is 500118158 Partitions will be aligned on 2048-sector boundaries Total free space is 2014 sectors (1007.0 KiB) Number Start (sector) End (sector) Size Code Name 1 2048 500118158 238.5 GiB 8300 Linux filesystem
dコマンドでパーティションを削除。
Command (? for help): d Using 1
再度、pコマンドでパーティションが削除されていることを確認。
Command (? for help): p Disk /dev/sdb: 500118192 sectors, 238.5 GiB Model: KINGSTON RBUSNS8 Sector size (logical/physical): 512/512 bytes Disk identifier (GUID): 5394AF49-2144-4AB8-9D79-BBFB489DCCBC Partition table holds up to 128 entries Main partition table begins at sector 2 and ends at sector 33 First usable sector is 34, last usable sector is 500118158 Partitions will be aligned on 2048-sector boundaries Total free space is 500118125 sectors (238.5 GiB) Number Start (sector) End (sector) Size Code Name
nコマンドでLVMパーティションを作成。GUIDコードは8E00を入力。LVMパーティションとなる。
Command (? for help): n Partition number (1-128, default 1): First sector (34-500118158, default = 2048) or {+-}size{KMGTP}: Last sector (2048-500118158, default = 500118158) or {+-}size{KMGTP}: Current type is 8300 (Linux filesystem) Hex code or GUID (L to show codes, Enter = 8300): 8E00 Changed type of partition to 'Linux LVM'
作成したパーティションを確認。
Command (? for help): p Disk /dev/sdb: 500118192 sectors, 238.5 GiB Model: KINGSTON RBUSNS8 Sector size (logical/physical): 512/512 bytes Disk identifier (GUID): 5394AF49-2144-4AB8-9D79-BBFB489DCCBC Partition table holds up to 128 entries Main partition table begins at sector 2 and ends at sector 33 First usable sector is 34, last usable sector is 500118158 Partitions will be aligned on 2048-sector boundaries Total free space is 2014 sectors (1007.0 KiB) Number Start (sector) End (sector) Size Code Name 1 2048 500118158 238.5 GiB 8E00 Linux LVM
wコマンドでパーティション情報をディスクに書込む。
Command (? for help): w Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING PARTITIONS!! Do you want to proceed? (Y/N): y OK; writing new GUID partition table (GPT) to /dev/sdb. The operation has completed successfully.
物理ボリューム作成
pvcreate
コマンドで/dev/sdbに物理ボリュームを作成。
# pvcreate /dev/sdb1 Physical volume "/dev/sdb1" successfully created.
物理ボリュームのボリュームグループへの追加
vgextend
コマンドで作成した物理ボリュームを既存のボリュームグループに追加
# vgextend ubuntu-vg /dev/sdb1 Volume group "ubuntu-vg" successfully extended
vgdisplay
でボリュームグループが拡張可能になったことを確認する
# vgdisplay --- Volume group --- VG Name ubuntu-vg System ID Format lvm2 Metadata Areas 2 Metadata Sequence No 3 VG Access read/write VG Status resizable MAX LV 0 Cur LV 1 Open LV 1 Max PV 0 Cur PV 2 Act PV 2 VG Size 702.73 GiB PE Size 4.00 MiB Total PE 179899 Alloc PE / Size 118850 / <464.26 GiB Free PE / Size 61049 / 238.47 GiB VG UUID eljjjs-eqqz-wes6-fkSC-SQUQ-P8wI-P4KETF
ボリュームグループの拡張
lvextend
でボリュームグループを拡張する。+100%FREEで追加した全領域全てを拡張する。
# lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv Size of logical volume ubuntu-vg/ubuntu-lv changed from <464.26 GiB (118850 extents) to 702.73 GiB (179899 extents). Logical volume ubuntu-vg/ubuntu-lv successfully resized.
vgdisplay
で論理ボリュームが拡張されたことを確認。
# vgdisplay --- Volume group --- VG Name ubuntu-vg System ID Format lvm2 Metadata Areas 2 Metadata Sequence No 4 VG Access read/write VG Status resizable MAX LV 0 Cur LV 1 Open LV 1 Max PV 0 Cur PV 2 Act PV 2 VG Size 702.73 GiB PE Size 4.00 MiB Total PE 179899 Alloc PE / Size 179899 / 702.73 GiB Free PE / Size 0 / 0 VG UUID eljjjs-eqqz-wes6-fkSC-SQUQ-P8wI-P4KETF
ファイルシステムの拡張
df
で確認したところ、ボリュームが拡張されてもファイルシステムは拡張されていない。
# df -kh Filesystem Size Used Avail Use% Mounted on tmpfs 778M 1.4M 777M 1% /run /dev/mapper/ubuntu--vg-ubuntu--lv 456G 6.3G 427G 2% / tmpfs 3.8G 0 3.8G 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 4.0M 0 4.0M 0% /sys/fs/cgroup /dev/sda2 976M 112M 798M 13% /boot /dev/sda1 511M 7.9M 504M 2% /boot/efi tmpfs 778M 4.0K 778M 1% /run/user/1000
resize2fs
で拡張したボリュームを拡張する。
# resize2fs /dev/ubuntu-vg/ubuntu-lv resize2fs 1.45.6 (20-Mar-2020) Filesystem at /dev/ubuntu-vg/ubuntu-lv is mounted on /; on-line resizing required old_desc_blocks = 59, new_desc_blocks = 88 The filesystem on /dev/ubuntu-vg/ubuntu-lv is now 184216576 (4k) blocks long.
df
で確認すると、ファイルシステムが拡張されていることが確認できた。
# df -kh Filesystem Size Used Avail Use% Mounted on tmpfs 778M 1.4M 777M 1% /run /dev/mapper/ubuntu--vg-ubuntu--lv 691G 6.3G 652G 1% / tmpfs 3.8G 0 3.8G 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 4.0M 0 4.0M 0% /sys/fs/cgroup /dev/sda2 976M 112M 798M 13% /boot /dev/sda1 511M 7.9M 504M 2% /boot/efi tmpfs 778M 4.0K 778M 1% /run/user/1000
これで、ファイルシステムの拡張は完了。
日本語化
タイムゾーンの変更
タイムゾーンはUTCになっているので、timedatectlコマンドでタイムゾーンをJSTに変更する。
# date Mon Feb 22 15:02:44 UTC 2021 # timedatectl set-timezone Asia/Tokyo # date Tue Feb 23 00:02:58 JST 2021
ロケールの変更
「Shift-JIS/EUC-JP死すべし慈悲はない」なので、ロケールはja_JP.UTF-8に。 日本語マニュアルも入れる。
# localectl set-locale LANG=ja_JP.UTF-8 # apt install -y language-pack-ja manpages-ja manpages-ja-dev
sambaのインストール
普通にapt install samba
でインストール。pdbedit
でユーザー追加
# sudo apt install samba # pdbedit -a [ユーザー名]
smb.confはglobal
セクションにWORKGROP名とNetBios名を追加。homes
セクションでホームディレクトリをWindows側から見えるように。
[global] workgroup = WORKGROUP netbios name = [ホスト名] [homes] comment = Home Directories browseable = no read only = no
鍵ペアによるsshログイン
インストール時にSSHサーバーを有効にしたので、鍵ペアをつかってWindowからログイン出来るようにする。
% ssh-keygen % cd .ssh % mv id_rsa.pub authorized_keys
出来たid_rsaをホストのWindowsのユーザーフォルダの下の.sshフォルダにコピー。
コマンドプロンプトからssh [ユーザー名]@[ホスト名]
でログイン出来る。
Windows Terminalの設定はこんな感じ。
{ (略) "profiles": { "list": [ (略) { "name": "[ホスト名](ssh)", "commandline": "ssh [ユーザー名]@[ホスト名]", "hidden": false, "icon": "(アイコンのパス)", "colorScheme": "Sakura" } ] } }
アイコンはUbuntuのアイコンをググって32x32にしてOneDriveに配置したのを参照。 カラースキームはWindows Terminal Themesから。カラースキームを変えることでログイン先を区別出来るようにした。
実験:空のstd::vectorから要素を取得するとどうなるか?
ふとした疑問
std::vectorには最後尾の要素を取得するbackというメソッドがあります。 もし、vectorが空の場合backメソッドを呼ぶとどうなるのか実験してみました。
書いたコードはこんな感じ。期待する動作は空要素を返すか、何らかの例外を投げてくれるか。
#include <vector> #include <string> #include <iostream> int main(int argc, char* argv[]) { std::vector<std::string> StrList; try { auto v = StrList.back(); std::cout << "Length = " << v.length() << std::endl; } catch (std::exception& e) { std::cout << "exception:" << e.what() << std::endl; } return 0; }
実験結果
試したのはbcc32c 7.40、MS-C 19.16.27026.1 、gcc 7.3.0、clang 6.0.0。gccとclangはWSLで確認。 結果は以下の通り。
コンパイラ | 結果 |
---|---|
bcc32c | 例外やエラーなし。 |
MS-C | 例外やエラーなし。 |
gcc | segmentation fault |
clang | segmentation fault |
Windows処理系だと、例外すら発生せずにどこかでコケている感じ。 bcc32cはデバッガで確認したり、Dinkumware STLのソースを確認すると、単に「end() - 1」だったので、そりゃあコケるわなと。
まとめのようなモノ
ということで、コンテナから要素を取り出す場合emptyとかでチェックしないと駄目というオチでした。
FireDAC / C++Builder のちょっとした小ネタ×3
その1:結果が1行、1列しかないデータを取得する場合
データベース開発をしていてよくあるのがクエリを発行して1個のスカラー値しか取らないケース。
例えば、連番とか、翌営業日とか、件数などなど。
こんな場合、TFDQuery::OpenメソッドでSQLを発行して、データセットから値を取得して、クローズするのはあまり「美しくない」です。
そんな場合に打って付けなのが、TFDConnection::ExecSQLScalarメソッドです。
このメソッドはTFDQuery::Openメソッドと同じようにクエリを発行するのですが、単一のスカラー値をVariantで返却します。データセットの操作とかは不要です。
文字通り、単一のスカラー値を取得する場合に使ってみて下さい。
その2:データ型マッピングと日付型
FireDACのデータ型マッピングを皆様お使いでしょうか?
この機能はRDBMSとクライアント間のデータ変換ルールを定義します。ドキュメントでは数値の変換ルールが記載されていますが、日時型はどうでしょうか?
FireDACというか、Delphi / C++Builderのデータセットで使われる日時型は以下の2つです。
さて、この両者の違いは秒未満の精度の違いです。RDBMSの日時型がどちらにマッピングされるのは、RDBMSに依存します。
FireDACのウリはマルチデータベース対応ですが、ここで依存性が発生するのはちょっとよろしくないです。
そこで、FireDAC接続エディタを使い明示的にマッピングすることで、日時型をどちらかに寄せることが出来ます。これで、TFDDConnectionで違うRDBMSに接続しても型変換を担保することが出来ます。
ちなみに、SQL ServerのDateTime2型は何もしないと文字列型にマッピングされます。
これは、データベースドライバの関係なので、SQL Native Client をインストールすることを強くお勧めします。(Microsoft SQL Server への接続(FireDAC) - RAD Studio)
その3:FireMonkeyとC++文字列リテラル
C++Builderで作ったライブラリをFireMonkeyのプロジェクトにポーティングをすることは良くあるかと思います。
プラットフォーム毎に文字列リテラルの文字コードを意識しないと文字化けします。
# ええ、テストプログラムで見事にやらかしました。
最近だと、Unicodeを意識して、文字列の接頭辞にuとかu8とかLとか付けますが、_D()マクロを使うとプラットフォームに合わせた接頭辞を選択してくれるので大変便利です。
詳細は、以下のDocWikiの記事を参考にしてください。
C++ におけるマルチデバイス アプリケーションについての考慮事項 - RAD Studio
Delphiでラムダ式
Delphi 10.3 Rioでは、Delphi言語のエンハンスとして、インライン変数宣言とインライン変数の型推論が導入されました。
これによりDelphiでラムダ式(無名メソッド)が書きやすくなりましたのでご紹介します。
ソースコードでラムダ式を使うメリットとしては以下が挙げられます。
- スレッドやコールバックのようなロジックをインラインで書くことによって可読性が向上する。
- 判定条件などの処理をオブジェクトとして持つことで記載が簡潔になる。
10.2まで、Delphiで無名メソッドを使用するにはTypeブロック内で以下のように宣言する必要があります。
program LTDel; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; type TMyFunc = reference to procedure(); var f0 : TMyFunc; f1 : TMyFunc; begin f0 := procedure begin WriteLn('Hello,') end; f1 := procedure begin WriteLn('World!') end; f0(); f1(); end.
そして、10.3 Rioからは、以下のように記述出来ます。ラムダ式を配列として宣言した例です。型推論のおかげでかなりラムダ式しています。
program LTDel; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; begin var f := [ procedure begin WriteLn('Hello,') end, procedure begin WriteLn('World!') end ]; f[0](); f[1](); end.
一見、ラムダ式は難しく見えますが、理解して使い始めた途端に可読性が良くなりますので、是非とも使ってみて下さい。
続・RAD Studio 10.2.2 Tokyo Starterをちょっとだけいじってみた。
今度はJCLとJVCLのインストールに挑戦。
JCLとJVCLはGetItからダウンロード・インストールできるのだけど、JVCLはパッケージがインストールされない。
コンパイル済みのバイナリがあるのだけど、こっちもこっちで同じ。
・30761 Jedi Code Library Snapshot Binary Installer for 10.2
http://cc.embarcadero.com/Item/30761
・30762 Jedi Visual Component Library Snapshot Bin-Installer 10.2
http://cc.embarcadero.com/Item/30762
仕方ないので、JVCLは上記のインストーラーの展開先から手動でインストール。
以下の手順で(多分)問題なし。
- C:\DelphiComponents\JVCL\packages\D25 Packages.groupprojをオープン
- プロジェクトグループから以下のパッケージを削除
- JvDotNetCtrls
- JvDotNetCtrlsDesign
- JvDB
- JvDBDesign
- 「プロジェクトマネージャ」から「全てをビルド」
- バイナリは、C:\Users\Public\Documents\Embarcadero\Studio\19.0\Bplにできるので、これらを[コンポーネント| パッケージのインストール]でインストール。
ただし、このままだとC++Buiderから使えないので、各プロジェクトオプションの[Delphiコンパイラ|出力 - C/C++]のC/C++ 出力ファイルの生成を「すべての C++Builder ファイル (パッケージ ライブラリを含む) を生成」に設定。
今日はここで力尽きた。やっぱり、Pro以上じゃないと駄目かな…。
RAD Studio 10.2.2 Tokyo Starterをちょっとだけいじってみた。
はてなダイアリーからはてなブログに移行しての第一弾。
ここ数年放置状態だったけど、これからは更新頻度が上がるはず。
ということで、RAD Studio 10.2.2 Tokyoのレビューのような物。
しかし、まぁ、立ち上げていきなりdark themeで立ち上がって驚いた。
Visual Studio CodeとかAtomのようなモダンなエディタの配色がこんな感じだから、その辺のトレンドに合わせてきたのかな。
Boostは最初からインストールされているのでは無く、NuGetのようにGetItからダウンロード。バージョンは2013年11月リリースの1.55。流石に旧コンパイラは無理だけど、せめてCLANGベースのは追随して欲しい。物は試しと1.66のビルドに挑戦したけどコンパイラがお亡くなりになったので断念。
折角だからアプリをビルドしてみたら以下のメッセージが表示。
MSBuildToolsPath is not specified for the ToolsVersion "14.0" defined at "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0", or the value specified evaluates to the empty string.
[致命的エラー] MSBuildToolsPath is not specified for the ToolsVersion "14.0" defined at "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0", or the value specified evaluates to the empty string.
どうも、64bitOSでレジストリの MSBuildの値に不整合があるみたい。
素直に当該部分(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0)を削除すればサクッと動作。
JVCLのようなサードパーティーのコンポーネントはどうなったのかは次のネタで。