それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

mac os で npm i がgyp エラーになるときのサクッとした対応

npm i がエラーになる

npm は利用しているmac のバージョンを見ていて、npm は該当のpython を呼びに行く 私の場合、最新版のmacOSはなるべく使わないことにしているので、python2 がないと怒られた。

takuya@~$ npm i
npm ERR! code 1
npm ERR! gyp verb check python checking for Python executable "python2" in the PATH
npm ERR! gyp verb `which` failed Error: not found: python2
(snip)
npm ERR! gyp ERR! stack   File "<string>", line 1
npm ERR! gyp ERR! stack     import sys; print "%s.%s.%s" % sys.version_info[:3];
npm ERR! gyp ERR! stack                       ^
npm ERR! gyp ERR! stack SyntaxError: invalid syntax

mac brew 環境での npm i の gyp 環境のエラーは、殆どの場合python パスのエラー

対応

python のバージョンを変えてあげる

pyenv local system
npm i

または、python2 を作ってあげる

ln -sr /usr/bin/python2.7 /usr/local/bin/python2

npm をどうやって入れたかによる。

再度インストール

rm node_modules/ -rf
npm i

node_modules に中途半端なコンパイルが残るので一回消しておくほうが無難。

それでもだめな場合

node のバージョンと、npm のバージョン、そしてパッケージのバージョンを見直す

要は、package.json に記載されたバージョンが古いままで、いまのnodeだとコンパイルが通らないとかある。

たとえば、node-sassの4.0x は最新のnodeだとインストール時にエラーになる。

npm -i # エラー(package.json が4 を指してる)
npm -i node-sass@4  # エラー
npm -i node-sass@6  # インストールできる

またはその逆で、nodeを古い方にあわせる

brew install node@14
brew unlink node
brew link node@14 --force-overwite 
npm i 
brew unlink node@14
brew link node

ruby gems をユーザ空間にインストールする

ユーザ空間を使う

sudo とかつかってグローバルを汚したくないし、bundler でプロジェクト単位にインストールも不便ってとき。

自分のユーザ空間の環境があるって最高ですよね。

ユーザ空間にgem をインストール

gem install --user-install PKG_NAME 

たとえば、nokogiri の場合

gem install --user-install nokogiri

また、この設定は、rbenv などでも使われていて普段意識することはないと思います。

デフォルトインストール先

現在の gem 環境設定を調べればいい

$ gem environment

私の場合は次のとおりだった。rbenv とruby-buildがあるのでちょっと複雑。

takuya@Desktop$ gem environment
RubyGems Environment:
  - RUBYGEMS VERSION: 3.1.2
  - RUBY VERSION: 2.7.1 (2020-03-31 patchlevel 83) [x86_64-darwin18]
  - INSTALLATION DIRECTORY: /Users/takuya/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0
  - USER INSTALLATION DIRECTORY: /Users/takuya/.gem/ruby/2.7.0
  - RUBY EXECUTABLE: /Users/takuya/.rbenv/versions/2.7.1/bin/ruby
  - GIT EXECUTABLE: /usr/local/bin/git
  - EXECUTABLE DIRECTORY: /Users/takuya/.rbenv/versions/2.7.1/bin
  - SPEC CACHE DIRECTORY: /Users/takuya/.gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: /Users/takuya/.rbenv/versions/2.7.1/etc
  - RUBYGEMS PLATFORMS:
    - ruby
    - x86_64-darwin-18
  - GEM PATHS:
     - /Users/takuya/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0
     - /Users/takuya/.gem/ruby/2.7.0
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => false
     - :bulk_threshold => 1000
     - :sources => ["http://rubygems.org/"]
     - "benchmark" => false
     - "gem" => "--no-document"
     - "install" => "--no-ri --no-rdoc"
     - "update" => "--no-ri --no-rdoc"
  - REMOTE SOURCES:
     - http://rubygems.org/
  - SHELL PATH:
     - /Users/takuya/.rbenv/versions/2.7.1/bin
     - /usr/local/Cellar/rbenv/1.2.0/libexec
     - /Users/takuya/.rbenv/shims
     - /Library/Frameworks/Mono.framework/Versions/Current/Commands
     - /Users/takuya/.composer/vendor/bin
     - /Users/takuya/.lib/node/bin
     - /Users/takuya/.rbenv/shims
     - /Users/takuya/.pyenv/shims
     - /usr/local/share/dotnet
     - /Users/takuya/.go/bin
     - /Users/takuya/.bin
     - ~/.dotnet/tools
     - /usr/local/sbin
     - /usr/local/bin
     - /usr/libexec
     - /opt/X11/bin
     - /usr/sbin
     - /usr/bin
     - /sbin
     - /bin

参考資料

phpstorm で scss-lintを行う

phpstorm でSCSSをチェックする

SCSSファイルを開くと、Lintの設定をレコメンドされる。配布元 →GitHub - idok/scss-lint-plugin: SCSS Lint plugin for intellij

ちなみにscss lint には npm もある。最近はnpmを使うことが多いハズ。そしてさらに最近はDartSassになってるはず。

ただし、このプラグインは設定が古いため、ruby 版を使うことになっている。

phpstorm のプラグインruby 版を想定してるので、想定通りに動かしてあげる。

私は更に想定して、古いバージョンのruby を使ってインストールしておいた。

scss-lintのインストール

gem install --user-install scss-lint

実行結果

Fetching scss-lint-0.38.0.gem
Fetching sass-3.4.25.gem
Fetching rainbow-2.2.2.gem
WARNING:  You don't have /Users/takuya/.gem/ruby/2.7.0/bin in your PATH,
      gem executables will not run.
Successfully installed sass-3.4.25
Building native extensions. This could take a while...
Successfully installed rainbow-2.2.2
WARNING: `scss-lint` has been renamed to `scss_lint` to follow proper RubyGems naming conventions. Update your Gemfile or relevant install scripts to install `scss_lint`.
Successfully installed scss-lint-0.38.0
3 gems installed

インストールされた場所

takuya@Desktop$ ls /Users/takuya/.gem/ruby/2.7.0/bin
sass  sass-convert  scss  scss-lint

設定

phpstorm などで、SCSSで設定を検索し、上記のパスを入れてあげる。

無事に動作した。

参考資料

pdoのprepareで名前に数字を入れると、bindValue出来ないエラー

php の pdo でエラーがでるので数日ずっと頭を抱えてた

出てくるエラー

: Invalid parameter number: number of bound variables does not match number of tokens

エラーは、php pdo の prepare statement で、execした時にエラーになる。

<?php
/// できる
$stmt->bindValue(":n1", $val );
$stmt->bindValue("n1", $val );
$stmt->bindValue("123n", $val );
///  出来ない
$sth->bindValue(':123', $val );
$sth->bindValue('123', $val );

エラーに気づかないわけ。

bindValue( $key, $value ) は $key が文字列だと、文字列インデックスでバインドし、ハッシュ :name から文字列キーを探す。

ところが、「数字に解釈できる文字列」だと、数字だと思って疑問符( = ? )に入れようと、該当の疑問符の数字インデックスを探す→見つからない→bindParamがありません。エラーとなる。

<?php
$sth->bindValue('123', $calories);   //
$sth->bindValue(':123', $calories);  // 123 番目を探しに行く

内部で$params[123] を探しに行く。そんなものあるわけがない。探してほしいのは $params[":123"] なんだよね 指定したけどintになる文字列だと、? を探しちゃってbindValue指定時のキーに入れられない。だからエラーになる。

しかもexecするまでわからない。(←ここが辛い)

コード作者はちゃんと値を入れてるから、値がないなんて考えないよね。でもbindValueエラーが出るんだよね。頭抱えるよね。

対策

文字列であることを明確にする

<?php
$key="123"
$sth->bindValue($key.'__', $v ); 

型変換怖い

原因がわかればなんてことないが、php7以降は「型」に強いと思ってると痛い目に遭う。

組み込み関数の型は相変わらず、自動変換される。phpは自動型推測で動いたのに、いまはソースコードに型を明示するようになったので、本当に気づかない。

とくに、SQLを自動生成してるとこのバグを踏みまくる。 随分前にこの仕様を踏んでめっちゃ頭を抱えた記憶があるのだが、7−8年越しにまた踏んで頭を抱えたので、メモ。

ここ数年はLaravelしか使わないし、PDOを素で使うことなんてないからこういうのすっかり忘れてハマりました。

systemdでネットワーク待ちを何とかする。Failed to start Wait for Network to be Configured.

ubuntu が起動時にエラーを吐いてネットワーク待ちで時間がかかる。

Failed to start Wait for Network to be Configured.

ネットワークを見てみる。

基本的に、networkdに管理させてないが、念のために確認する。

takuya@:~$ networkctl
IDX LINK            TYPE     OPERATIONAL SETUP
  1 lo              loopback carrier     unmanaged
  2 eth0            ether    carrier     unmanaged
  3 br0             bridge   routable    unmanaged
  4 lxcbr0          bridge   no-carrier  unmanaged
  5 docker0         bridge   no-carrier  unmanaged
 52 br-8938dceff93b bridge   routable    unmanaged
 54 veth61a80a4     ether    carrier     unmanaged

network-onlineを編集

systemd で上記のネットワークを無視してあげる

takuya@:~$ /lib/systemd/systemd-networkd-wait-online --help
systemd-networkd-wait-online [OPTIONS...]

Block until network is configured.

  -h --help                 Show this help
     --version              Print version string
  -q --quiet                Do not show status information
  -i --interface=INTERFACE[:MIN_OPERSTATE[:MAX_OPERSTATE]]
                            Block until at least these interfaces have appeared
     --ignore=INTERFACE     Don't take these interfaces into account
  -o --operational-state=MIN_OPERSTATE[:MAX_OPERSTATE]
                            Required operational state
     --any                  Wait until at least one of the interfaces is online
     --timeout=SECS         Maximum time to wait for network connectivity

See the systemd-networkd-wait-online.service(8) man page for details.
takuya@:~$

設定を編集

sudo systemctl edit systemd-networkd-wait-online

無視を追加

[Service]
ExecStart=/lib/systemd/systemd-networkd-wait-online \
  --ignore=docker0 \
  --ignore=lxcbr0 \
  --ignore=eth0 \
  --timeout=20

後は様子見。

参考資料

https://qiita.com/tsuru2_mitsuru/items/f3041cdb11dff18eb5c3

btrfs 内部にスワップ・ファイルを設置する

btrfs はカーネル5 からswap をサポートした

## 空のファイル
sudo truncate -s 0 /swap.img
## CoW / 圧縮を無効に
sudo chattr +C /swap.img
sudo btrfs property set /swap.img compression none
## chmod 
sudo chmod 600 /swap.img
## swap サイズため容量確保
sudo fallocate -l 1G /swap.img
### 容量確認
sudo ls -ald /swap.img
### SWAPを有効に
sudo mkswap   /swap.img
sudo swapon /swap.img
### swap を無効に
sudo swapoff /swap.img

状態確認

swapon
NAME      TYPE  SIZE USED PRIO
/swap.img file 1024M   0B   -2

一通りできたら、fstabへ

sudo vim /etc/fstab 

マウントを書く

/swap.img swap swap default 0 0

https://www.unixtutorial.org/create-swap-from-file-on-btrfs-filesystem/ https://wiki.archlinux.jp/index.php/Btrfs#.E3.82.B9.E3.83.AF.E3.83.83.E3.83.97.E3.83.95.E3.82.A1.E3.82.A4.E3.83.AB

パーティションをディスクに仕立てる(壊れたパーティションの先頭を作り直す)

達成したい目的。

LVM から ext4を取り出して、単独でブートするように作り直したい。

言い換えると

パーティションなんて、HDDの先頭にセクタ位置を書いてるだけだろ?とおもって調べたらやっぱりそうだった。

準備。

新規インストールで実験環境を整える。

サクッとインストールして、ext4 on LVM を用意する。 ext4 on LVM でインストールしたLinux仮想マシンで作成。

sudo virt-install \
  --connect=qemu:///system  \
  --name lc01   \
  --ram 8192   \
  --disk path=/var/lib/libvirt/images/lc01.qcow2,size=5  \
  --vcpus 8  \
  --virt-type kvm   \
  --os-variant debian10   \
  --graphics none   \
  --location http://ftp.kddilabs.jp/pub/Linux/distributions/Debian/debian/dists/buster/main/installer-amd64/   \
  --extra-args="console=ttyS0" \
  --check all=off

ext4 を取り出す。

qcow2 から raw ファイルを取り出す。

sudo qemu-img convert -p -f qcow2 le01.qcow2 -O raw le01.img

ループバックにつなぐ

sudo losetup -P -f le01.img --show

LVMが接続されるのを確認する。

pvs
vgs
lvs 

接続されたLVMから ext4 を抜き出す。

sudo ddrescue /dev/mapper/le01--vg-root vgroot.img

後片付けする。

vgchange -an le01-vg
sudo losetup -d /dev/loopX

取り出したext4

取り出したファイルがEXT4なことを確認

$ file vgroot.img
vgroot.img: Linux rev 1.0 ext4 filesystem data, UUID=33cc43c6-b3f7-4001-9460-d6d28f11d91f (extents) (64bit) (large files) (huge files)

ext4 パーティションをディスクイメージに変換する。

取り出したパーティションをディスクイメージに変換する。

ext4 の先頭に1Mを追加する。

ext4のイメージファイルの先頭に1MBを足せばいいのですが。

ファイルの先頭に1Mを追加するという処理は面倒です。

そこで、1Mのファイルを作って末尾にExt4を追記するという逆のアプローチでやります。

パーティションヘッダを作る

dd または truncate で1MiB のファイルを作る。

dd if=/dev/zero of=new-hdd.img count=1 bs=1MiB

パーティションとは、ファイルシステムの先頭に、1MBがあるだけです。 bs=1MiB と書くのに注意。

先頭に16kがあり、どのセクタにファイルシステムがあるか書いてる。 GPTは16k-1M までの領域にEFIとかUUIDとか色々書いてるらしい。

1MB+ext4 => ディスクイメージ

pv とリダイレクトを用いて追記します。

pv vgroot.img  >> new-hdd.img

ディスクイメージをコピーすると時間がかかるのでcp よりもpv の方が扱いやすい。

これで、パーティションがぶっ壊れたHDDイメージの出来上がり。

パーティションを作り直す。

先頭が空っぽなので、パーティションとして認識されません。

パーティションが消えた状態になっています。

takuya@:images$ fdisk -l new-hdd.img
Disk new-hdd.img: 3.56 GiB, 3826253824 bytes, 7473152 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

fdisk を使ってパーティションを作り直します。

takuya@:images$ sudo fdisk  new-hdd.img

Welcome to fdisk (util-linux 2.36.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0xb2368926.

Command (m for help): p # ← print
Disk new-hdd.img: 3.56 GiB, 3826253824 bytes, 7473152 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xb2368926

Command (m for help): n # ← new
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p # ← primary
Partition number (1-4, default 1):
First sector (2048-7473151, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-7473151, default 7473151):

Created a new partition 1 of type 'Linux' and of size 3.6 GiB.
Partition #1 contains a ext4 signature.

Do you want to remove the signature? [Y]es/[N]o: no # ←既存を使うのでno

The signature will be removed by a write command.

Command (m for help): p # ← print
Disk new-hdd.img: 3.56 GiB, 3826253824 bytes, 7473152 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xb2368926

Device       Boot Start     End Sectors  Size Id Type
new-hdd.img1       2048 7473151 7471104  3.6G 83 Linux

Filesystem/RAID signature on partition 1 will be wiped.

Command (m for help): a # ← Make MBR bootable flag on
Selected partition 1
The bootable flag on partition 1 is enabled now.

Command (m for help): w # ← Write and Quit
The partition table has been altered.
Syncing disks.

これでパーティションとして認識されるはずです。

takuya@:images$ fdisk -l new-hdd.img
Disk new-hdd.img: 3.56 GiB, 3826253824 bytes, 7473152 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xb2368926

Device       Boot Start     End Sectors  Size Id Type
new-hdd.img1 *     2048 7473151 7471104  3.6G 83 Linux

ファイルを確認

ext4 が壊れてないか確認しておきます。

イメージファイルををループバックで接続してみます。

losetup -P -f new-hdd.img --show

接続できたのでパーティションが認識されるはずです。確認しておきます。

takuya@:images$ lsblk
NAME            MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
loop11            7:11   0   3.6G  0 loop
└─loop11p1      259:4    0   3.6G  0 part

マウントしてみます。あらら失敗です

sudo mount /dev/loop11p1 test
mount: /var/lib/libvirt/images/test: wrong fs type, bad option, bad superblock on /dev/loop11p1, missing codepage or helper program, or other error.

dmesg を確認してみます。どこか失敗した模様(ddのbsミス でした)

$ sudo dmesg
[694912.138454] EXT4-fs (loop11p1): bad geometry: block count 933888 exceeds size of device (933883 blocks)
[694917.971654] EXT4-fs (loop11p1): bad geometry: block count 933888 exceeds size of device (933883 blocks)
[695308.681524] EXT4-fs (loop11p1): bad geometry: block count 933888 exceeds size of device (933883 blocks)
[695314.313132] EXT4-fs (loop11p1): bad geometry: block count 933888 exceeds size of device (933883 blocks)
[695351.389589] EXT4-fs (loop11p1): mounted filesystem with ordered data mode. Opts: (null)
[695371.450113] EXT4-fs (loop11p1): mounted filesystem with ordered data mode. Opts: (null)

やり直しました。問題なさそうです。

$ sudo fsck /dev/loop11p1
fsck from util-linux 2.36.1
e2fsck 1.46.2 (28-Feb-2021)
/dev/loop11p1: clean, 28743/233856 files, 286271/933888 blocks
$ sudo e2fsck -f /dev/loop11p1
e2fsck 1.46.2 (28-Feb-2021)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/loop11p1: 28743/233856 files (0.2% non-contiguous), 286271/933888 blocks
$ sudo resize2fs /dev/loop11p1
resize2fs 1.46.2 (28-Feb-2021)
The filesystem is already 933888 (4k) blocks long.  Nothing to do!

GPTに変更する

今どきのディスクはGPTなのでGPTでもできるが、、EFIパーティションとか、MBRハイブリッドとか考えることが多いので今回はパス。

ブートの修正

ブート修正は取り出したイメージをマウントして修正します。

マウント

losetup -f -P --show new.img
mount /dev/loop11p1 /mnt

chrootする

cd /mnt
sudo mount -t proc proc proc/
sudo mount -t sysfs sys sys/
sudo mount -o bind /dev dev/
#
sudo chroot . /bin/bash

ブート修正。

grub-install /dev/loop11
## 作業PCの boot を拾ってマルチブートになるのを避ける
chmod a-x /etc/grub.d/30_os-prober 
update-grub
update-initramfs -u

作業が終わったら後片付けする

sudo umount -lf ./sys
sudo umount -lf ./proc
sudo umount -lf ./dev
cd 
umount /mnt
losetup -d /dev/loopX

update-grub は次が出れば成功

Found linux image: /boot/vmlinuz-xxxx-generic
Found initrd image: /boot/initrd.img-xxx-generic

出てこない場合は、 /boot にファイルがないはずなので、/bootが別パーティションにありddできてない可能性がある。/bootを取り損ねていないか確認。見つけ次第コピー

LVMを停止関連

LVM を停止してデータを取り出したので、以前のLVM関連の設定が残らないようにする。

lvm バックアップを削除

rm /etc/lvm/backup/le01-vg

スワップファイル

LVM のスワップがあるときは、スワップファイルを作り直してlvmスワップを除去

sudo vim  /etc/initramfs-tools/conf.d/resume 

スワップファイル再生成

sudo dd if=/dev/zero of=/swap.img bs=1M count=1000
sudo chmod 600 /swap.img 
mkswap /swap.img 

fstab のスワップ設定を変える

sudo vim /etc/fstab

LVM除去が終わったら

update-grub
update-initramfs -u

その他の問題 btrfs

btrfs の場合 update-initramfs -uが次のエラーになるので。

/sbin/fsck.btrfs doesn't exist, can't install to initramfs

ダミーで対応する。

sudo  cp /bin/true /sbin/fsck.btrfs

その他の問題 GRUB /boot

/boot の中身をコピーし忘れたときは、単純に grub だけが起動する。

grub で、not found になるときはコピーし忘れ

grub > ls 
grub > set root=(hd0,1)
grub > ls /vmlinuz
file not found 

その他の問題 GRUB lvm 除去漏れ

lvm → ext4 に変えたとき、update-initramfs をせずに起動すると、LVMを探しに行ってgrub 付近でエラーになることが有る。

そのときは、手作業で起動してみる

ディスクの確認

grub > ls 

root の設定

grub > set root=(hd0,1)

uuidを確認

grub > ls (hd0,1)
        Partition hd1,3: Filesystem type ext4- Last modification time...
2022-05-23 07:49:05 Sunday, UUID FFEXXX-5X23456

カーネルを起動する

grub > linux /vmlinuz quiet s root=UUID-FFEXXX-5X23456
grub > initrd /boot/initrd.img
grub > boot
grub メモ

MBRパーティションは次のように表示される。dosが入ってるわけでなくDOS/V用のMBRパーティションの意味である。

(hd0,msdos1)

これは、msdosを省略でアクセスできる

set root=(hd0,1)
set root=(hd0,msdos1) # 同じ

gpt ( (hd0,gpt1) ) についても同じだと思う。

まとめ

ディスク内のパーティションの管理は、先頭1MiBで行っている。

単純なext4 イメージに先頭1MiBをつければディスクイメージに変えられるとわかった。

lvm の内部にあるパーティションも強引に取り出して先頭をつければ、単純なディスクイメージに変更できるとわかった。

先頭1MiB について

先頭の1MiBが使われているのは fdisk で確認できます。

sudo sgdisk -p /dev/nvme0n1
Sector size (logical/physical): 512/512 bytes


Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         1050623   512.0 MiB   EF00
   3         3147776      4000794623   1.9 TiB     8300

ssd/HDDの中身は、2048 セクタから書きます。

1セクタは、512 バイトです。

パーティション1は2048セクタから開始してます。先頭-2047にはext4 は存在しません

先頭-2047セクタ分、つまり2048セクタが管理用に予約され使われているわけです。

この2048セクタのバイトサイズを計算すると・・・1セクタ=512バイトだから

2048 セクタ
⇔ 512バイトx 2048 
⇔ 512 x 2x 1024 バイト 
⇔  1024x 1024 バイト
⇔ 1048576 バイト
⇔ 1MiB

だから先頭に1MiBをつけておけば、ext4のシンプルボリュームをディスクイメージとして使えるってことなんだろうな。

大昔のFDDの頃は容量節約のために1セクタ=128/256/512バイトなど、サイズは自分で決められたらしい。むかし先輩にちらっと聞いたけど、当時はよくわからんけどなんか便利な単位なんですねって聞き流してた。が、まさか今更役に立つなんて。

参考資料

btrfs resize で進捗を見たい

btrfs filesystem resize をしてると、ちゃんと動いてるのか不安になる。

大きいデータファイルだと余計に不安になる。

dmesg を見ればいいらしい

dmesg  | grep BTRFS | tail

watch とかやっておけばいい

実際にやってみた例

Every 2.0s: dmesg  | grep BTRFS | tail                                                                                                                                                                                     host: Sat May 21 18:28:18 2022

[575124.384097] BTRFS info (device dm-2): relocating block group 761060179968 flags data
[575224.816851] BTRFS info (device dm-2): found 549 extents
[575226.307604] BTRFS info (device dm-2): found 549 extents
[575227.461641] BTRFS info (device dm-2): relocating block group 759986438144 flags data
[575334.728443] BTRFS info (device dm-2): found 1375 extents
[575336.185406] BTRFS info (device dm-2): found 1375 extents
[575337.135120] BTRFS info (device dm-2): relocating block group 758912696320 flags data
[575438.211646] BTRFS info (device dm-2): found 48 extents
[575439.111490] BTRFS info (device dm-2): found 48 extents
[575439.794408] BTRFS info (device dm-2): relocating block group 757838954496 flags data

終了したら

[575641.955655] BTRFS info (device dm-2): new size for /dev/mapper/vgubuntu-root is 214748364800

などと出てくくる。

まぁ終了したらコマンド見たらわかるんだけど。

参考資料

https://unix.stackexchange.com/questions/398115/btrfs-filesystem-resize-doesnt-do-anything

ext4 → btrfs にファイルシステムを変換する。

ext4 → btrfs に変更

gitlabストレージに使ってるHDDが、よく考えたら大量のwordpressだらけで、はっきり言って容量の無駄使いなので、btrfs に変えて重複ファイルの排除機能を使えば節約になりそうな気がした。

手順1

fsck でエラーを修正しておく

fsck /dev/mapper/storage-root

手順2変換する

使うコマンドはbtrfs-convert である。進捗をだすために -p を見ている

btrfs-convert -p /dev/mapper/vgubuntu-root

create btrfs filesystem:
        blocksize: 4096
        nodesize:  16384
        features:  extref, skinny-metadata (default)
        checksum:  crc32c
creating ext2 image file
creating btrfs metadata
copy inodes [O] [    698961/    313176]
conversion complete

ただし、一時ファイルが必要みたい 進捗を見る限り直接ファイルシステムを変更するわけではなく、一時ファイルを経由するみたいだから、多少の空き容量が必要であると予想される。

creating ext2 image file

変換結果の確認

変換された結果を閲覧する。btrfs はマウントしてデータを見る。

sudo mount /dev/mapper/vgubuntu-root ./disk
sudo btrfs filesystem show ./disk

実際の動作例。

sudo btrfs filesystem show disk
[sudo] password for takuya:
Label: none  uuid: 7f7eb691-81a0-4184-89cb-a8d3b67c8672
        Total devices 1 FS bytes used 90.58GiB
        devid    1 size 498.54GiB used 117.37GiB path /dev/mapper/vgubuntu-root

btrfs の機能である重複排除や透過圧縮が聞いてるとディスクサイズがガラッと変わってくる。

df を見る

btrfsdf がつかえなくなる(あてにならない)ので、btrfs df コマンドを代わりに使う。

sudo btrfs filesystem df ./disk

実際の例。

sudo btrfs filesystem df ./disk
Data, single: total=115.22GiB, used=90.81GiB
System, single: total=4.00MiB, used=112.00KiB
Metadata, single: total=1.45GiB, used=450.69MiB
GlobalReserve, single: total=110.61MiB, used=0.00B

df よりusage のほうが見やすいので私はこっちが好き

sudo btrfs filesystem usage ./disk
Overall:
    Device size:                 498.54GiB
    Device allocated:            115.60GiB
    Device unallocated:          382.94GiB
    Device missing:                  0.00B
    Used:                         90.65GiB
    Free (estimated):            406.87GiB      (min: 406.87GiB)
    Data ratio:                       1.00
    Metadata ratio:                   1.00
    Global reserve:              110.33MiB      (used: 16.00KiB)

Data,single: Size:114.14GiB, Used:90.21GiB (79.03%)
   /dev/mapper/vgubuntu-root     114.14GiB

Metadata,single: Size:1.45GiB, Used:450.42MiB (30.27%)
   /dev/mapper/vgubuntu-root       1.45GiB

System,single: Size:4.00MiB, Used:112.00KiB (2.73%)
   /dev/mapper/vgubuntu-root       4.00MiB

Unallocated:
   /dev/mapper/vgubuntu-root     382.94GiB

マウントを変更する ext4 → btrfs

btrfs に変更されると、ディスクのUUIDが変わるので、マウントを変えてあげないとだめなことがある。

私の場合は、/dev/mapperで指定してたので、UUIDは使ってないので特にUUID変更の必要はなかった。

ただし、ファイルシステムについては、fstabext4 を記載部分を btrfs に変更する必要があった。

before

# /etc/fstab: static file system information.
# <file system> <mount point>   <type>  <options>       <dump>  <pass>

# /dev/mapper/vgubuntu-root /               ext4    errors=remount-ro 0       1
/dev/mapper/vgubuntu-root /               btrfs   errors=remount-ro 0       1

UUIDでマウントをしている場合は、uuidも手動で変更してあげる。

mount /dev/mapper/xxx-root disk
blkid 
vim disk/etc/fstab

マウントオプション

btrfs にはいくつかオプションがあるので、マウントオプションを検討する。(後述)

通常は変換後は、ただ何も考えずに使えばいい。

サイズを調整する。

任意。btrfs でディスクサイズがいい感じに節約されたときは、リサイズを掛けたくなるとおもう。

縮小

btrfs filesystem resize -100GB ./disk

拡大

btrfs filesystem resize +10GB ./disk

指定サイズへ

btrfs filesystem resize 300GB ./disk

パーティション最大へ

btrfs filesystem resize  max ./disk

マウントオプションによるチューニング

CoW の有効無効に注意する

CoWを有効化するかどうか。Raspberry Pi のようなSDカードメインだとCoWは著しく寿命を縮める可能性があるが、ログファイルなどは、journalctl で volalite(揮発性)にしてしまえばCoWがenabledでも問題なさそうだ。DBストレージの場合は、DBが入ってるディレクトリだけchattr してあげたほうが良さそう。

圧縮の有効無効

圧縮を透過圧縮にするかどうか、これも検討した方がいい。テキストファイルを扱うことが多いなら透過圧縮はストレージ容量を大幅に節約することができると思う。とくにgitlab のようなテキストファイルを大量に扱うストレージなら、btrfs で重複排除されるうえに、文字列が多いので圧縮が非常に効くと思う。ただし物理的破損がおきたらデータ喪失量も膨大になりそうだ。ちょっと諸刃の剣。CPU負荷も少し上がりそうだよね。書き込み総量が少なくなるので、SSDの寿命に優しくなるので、電気代・書き込み量・扱うデータを考えて、こちらも少し思案したほうが良さそう。設計に困ったら、特定のディレクトリだけを圧縮するchattr が使えるのでbtrfs は強い。

ext4→btrfs変換後に再圧縮(初期圧縮)をかける

btrfs filesystem defragment -r -v -c XXX /

trim で SSD TRIM
マウントオプション discard=asyncで、自動的にtrim が実行される。コミット待ちが発生するので、メモリ量と書き込み頻度と相談。

その他のマウントオプション

  • ssdSSD最適化された動作の一部をオンにします
  • ssd_spread: 大きな空き領域を一括で割り当てることでパフォーマンスの向上を図るらしい。
  • inode_cache: 空きinode番号のキャッシュを有効にします。

メンテナンス

最低限のメンテナンス手順だけ覚えておく

btrfs filesystem defragment -r ./disk
btrfs scrub ./disk
#  btrfs check ./disk # 普通はやらない

参考資料

UbuntuのUSBメモリの作り方と起動

UbuntuUSBメモリの作り方

unetbootinを使う場合

unetbootin を起動します。

ディストリビューション選択し、インストールするUSBメモリを選びます。

リブート後の保存領域のサイズを決めます。

UbuntuのISOファイルが自動的にダウンローされます。

Ubuntuのダウンロードが遅い場合は、自分で最速ミラーを探せば問題ないでしょう。

Rufus を使う場合

他のソフトウェアとしてRufusをインストールします。

ISOファイルの準備

Rufusを使う場合。さきに、UbuntuのISOファイルを入手しておきます。

Windows コマンドプロンプトを起動します。

ダウンロードコマンドは次のとおりです。

curl -LJO http://ftp.jaist.ac.jp/pub/Linux/ubuntu-releases/22.04/ubuntu-22.04-live-server-amd64.iso

ダウンロードが終わるのを待ちます。

Rufusを起動します。

ISOファイルを選び、Persistentサイズ(永続化サイズ)を数GB確保しておきます。

USBメモリをパソコンに差し込みます。

電源をいれ、F12連打します。

F12は、起動するHDD/SSD選択画面を表示するキーです。機種によってはF1/F2/F8であることもあります。

最上位のもの選んでEnter

最初に表示されるのは、USBメモリ内部にあるOS選択画面です。

特に選択は必要ありませんが、一番上を選びます。

Ubuntuが起動します。

以上

Ubuntu が起動するUSBメモリは、15分ほどで作ることができます。

サイズは8GB程度あれば十分です。32GBは多いくらいですが、500円-1000円までで購入可能であれば問題ないと思います。

UbuntuのUSBメモリ起動でHDDのクローンとバックアップを作る

UbuntuUSBメモリ起動でHDDのクローンとバックアップを作る

作業前の注意

練習すること。 実際にバックアップを取得する前に、練習すること。

練習は、データが消えてもいいUSB-HDDや安いUSBメモリを使う。SDカードでもいいので練習しておく。

ubuntu の起動

USBメモリを挿し込んでパソコンを起動します。 パソコンにUSBメモリを差し込み、USBメモリから起動を選びます。

起動するストレージを選択するキーを連打して電源を入れます。(F12など)

Ubuntu の起動を待つ

選択したら、起動を待ちます。 起動しました

gparted を使う場合

gparted は Linux で一般的に使われるHDD・SSDの管理ツールです。

ディスクのクローンやイメージ化吸い出し、コピー、初期化、サイズ変更などメンテナンスが行なえます。

gparted を起動します。

バックアップ(クローン)を作成ディスクを選びます。 どこのディスクをどこへクローンするか選びます。

ddrescue を使う場合

コマンドからやるほうが、作業が明確になりミスが減ると思います。

ddrescueの準備(インストール)

ddrescue は自分でインストールする必要があります。

Terminalを起動します。

すべてのプログラムから、ターミナルを起動します

universe レポジトリを追加します。

sudo add-apt-repository universe

ddrescue をインストールします。

sudo apt install gddrescue

ddrescue でバックアップ

ターミナルで次のコマンドを実行

lsblk で接続しているディスクの一覧を見れます。

lsblk 

ddrescue を実行します。

ddrescue /dev/sdX /dev/sdY

以上

バックアップは、UbuntuUSBメモリがあれば手軽に作ることができます。

緊急時に備えて、避難訓練をやっておいて損はないと思います。

lxc で hostnamectl が動かない。

lxc rename の問題。

lxc rename でインスタンス名を変更したが、ホストにログインしたときの名前が変わってない。

hostnamectl が動かない。

ホスト名を変えようと思ったけど動いてない。

root@lxc-instance01:~# hostnamectl set-hostname myserver01
Could not set property: Connection timed out

hostnamectl は systemd なので、そっちを見に行く。

root@lxc-instance01:~# systemctl status systemd-hostnamed
● systemd-hostnamed.service - Hostname Service
     Loaded: loaded (/lib/systemd/system/systemd-hostnamed.service; static)
     Active: failed (Result: exit-code) since Tue 2022-05-17 22:33:53 JST; 49s ago
       Docs: man:systemd-hostnamed.service(8)
             man:hostname(5)
             man:machine-info(5)
             man:org.freedesktop.resolve1(5)
    Process: 902 ExecStart=/lib/systemd/systemd-hostnamed (code=exited, status=226/NAMESPACE)
   Main PID: 902 (code=exited, status=226/NAMESPACE)

May 17 22:33:52 lxc-instance01 systemd[1]: Starting Hostname Service...
May 17 22:33:53 lxc-instance01 systemd[902]: systemd-hostnamed.service: Failed to set up mount namespacing: /run/systemd/unit-root/proc: Permission denied
May 17 22:33:53 lxc-instance01 systemd[902]: systemd-hostnamed.service: Failed at step NAMESPACE spawning /lib/systemd/systemd-hostnamed: Permission denied
May 17 22:33:53 lxc-instance01 systemd[1]: systemd-hostnamed.service: Main process exited, code=exited, status=226/NAMESPACE
May 17 22:33:53 lxc-instance01 systemd[1]: systemd-hostnamed.service: Failed with result 'exit-code'.
May 17 22:33:53 lxc-instance01 systemd[1]: Failed to start Hostname Service.

だめっぽい。

非特権コンテナなので、ファイルにアクセスできないので、変えられない。LXCの設計上の問題っぽいですね。ファイルを編集するかホスト側から制御しなくちゃだめなのかも。

root@:~# ls -alt /run/systemd/unit-root/proc
ls: cannot access '/run/systemd/unit-root/proc': No such file or directory

対応、直接ファイルを編集

昔ながらの方法で、ファイルを編集して対応する。

vim /etc/hostname
vim /etc/hosts
shutdown -r 

debian で発生した。ubuntu の場合発生しなかった。

rclone の sftp で接続エラーになる

rclone の sftp が接続できない

rclone で sftp が接続エラーになる。

接続ログを見ながら接続

rclone -vvv lsd test:

接続エラー

2022/05/17 16:12:41 DEBUG : Using config file from "/root/.config/rclone/rclone.conf"
2022/05/17 16:12:41 DEBUG : pacer: low level retry 1/10 (error couldn't connect SSH: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain)

sftp コマンドではつながる

sftp test
sftp> ls /

接続できる。

サーバー側のエラーを見る

userauth_pubkey: key type ssh-rsa not in PubkeyAcceptedAlgorithms [preauth]

rclone はrsaの接続方式の一部をスキップしてる。SSHサーバ側ではRSA鍵をAccept出来ない。

サーバー側で設定を追加

/etc/ssh/sshd_config

#PubkeyAuthentication yes
PubkeyAcceptedKeyTypes=+ssh-rsa

再起動

systemctl reload sshd

よくわからない。。。

rclone の接続は通常のSFTPライブラリをどう使ってるんですかねぇ。

sftp のコマンドでつながるし、同じ鍵を使ってるんですけどねぇ。

vim 追加コピー

vim で追加コピーをやる方法

過去の調べているだが、すっかり忘れている。

以前のエントリ

vim で追加カット・追加コピー - それマグで!

vim で追加コピー

追加切り取り

:map dEd "edd
:map ded "Edd

追加コピー

:map yEe "eyy
:map yee "Eyy

ヤンクレジスタ に登録して、追加コピーする。

vimdiff と組み合わせると便利すぎてやばい。

map して使うのが一番いい。

lxc の btrfs ストレージがぶっ壊れたときの記録

lxc のインスタンスの動作が微妙におかしいので、停止してみみてみた。

srubでエラーになる。

there are uncorrectable errors

エラーを見てくる。、

dmesg| grep -e "BTRFS warning.*path:"
dmesg| grep -e "BTRFS warning.*path:" | sed -e 's/^.*path\: //'

LXCのログも見る。

lxc monitor --type=logging --pretty

ログを見ながらscrubする

btrfs scrub start /mnt
journalctl --dmesg -f --grep 'BTRFS'
-- Logs begin at Thu 2020-09-10 14:48:11 JST. --

May 13 04:37:05 m75q-1 kernel: BTRFS error (device loop1): bdev /dev/loop1 errs: wr 704175, rd 69641, flush 0, corrupt 0, gen 0
May 13 04:37:05 m75q-1 kernel: BTRFS error (device loop1): bdev /dev/loop1 errs: wr 704175, rd 69642, flush 0, corrupt 0, gen 0
May 13 04:37:05 m75q-1 kernel: BTRFS error (device loop1): bdev /dev/loop1 errs: wr 704175, rd 69643, flush 0, corrupt 0, gen 0
May 13 04:37:05 m75q-1 kernel: BTRFS error (device loop1): unable to fixup (regular) error at logical 221216776192 on dev /dev/loop1
May 13 04:37:05 m75q-1 kernel: BTRFS error (device loop1): unable to fixup (regular) error at logical 221216247808 on dev /dev/loop1
May 13 04:37:05 m75q-1 kernel: BTRFS error (device loop1): unable to fixup (regular) error at logical 221216903168 on dev /dev/loop1
May 13 04:37:05 m75q-1 kernel: BTRFS error (device loop1): unable to fixup (regular) error at logical 221216780288 on dev /dev/loop1
May 13 04:37:05 m75q-1 kernel: BTRFS warning (device loop1): i/o error at logical 221216641024 on dev /dev/loop1, physical 193282576384, root 4115, inode 103249193, offset 76156928, length 4096, links 1 (path: rootfs/var/log/journal/67abe395f45b472>
May 13 04:37:05 m75q-1 kernel: BTRFS warning (device loop1): i/o error at logical 221215981568 on dev /dev/loop1, physical 193281916928, root 4115, inode 103249193, offset 75497472, length 4096, links 1 (path: rootfs/var/log/journal/67abe395f45b472>
May 13 04:37:05 m75q-1 kernel: BTRFS info (device loop1): scrub: finished on devid 1 with status: 0
May 13 04:49:16 m75q-1 kernel: BTRFS info (device loop1): scrub: started on devid 1

ハードウェアエラーだって・・・・

Ideally, a corrupt checksum only happens due to hardware issues (e.g., "bit rot" on disk). 

その状態でもbtrfs restore はできるので、btrfs のスナップショットとサブボリュームの管理がlxdからうまく行えてないんじゃないかと疑問を感じた。

btrfsの場合、マウントできるのでファイルを取り出した。

lxc storage list | grep default 
pv /var/snap/lxd/common/lxd/disks/default.img | pigz default.img.gz
losetup -f --show /var/snap/lxd/common/lxd/disks/default.img
mount /dev/loopX /mnt
snap stop lxd
btrfs scrub /mnt
btrfs restore /dev/loopX