それマグで!

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

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

仮想マシンのqemu - qcow2 のイメージに 変換する。(raw->qcow2, ova->qcow2)

VirtualBoxのイメージを変換する。

まぁそのままでも動くんだけど、管理を統一したいので qcow2 にする。 パフォーマンス云々はあるだろうけど。そこま気にしないことにする。

qemu コマンド

次のコマンドを使う。

qemu-img convert

ファイル名を指定する。

qemu-img convert -O qcow2 input.raw output.qcow2

拡張子は任意である。

実際の例

マイクロソフトが配布する MSEged 用のova イメージをqcow2 に変換しています。

takuya@:~$ qemu-img convert MSEdge\ -\ Win10.ova -O qcow2 MSEdge\ -\ Win10.qcow2

出来上がりを確認する。

takuya@:~$ qemu-img info MSEdge\ -\ Win10.qcow2
image: MSEdge - Win10.qcow2
file format: qcow2
virtual size: 6.8G (7255876608 bytes)
disk size: 6.8G
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: false
    refcount bits: 16
    corrupt: false
takuya@m75q-1:~$ qemu-img info MSEdge\ -\ Win10.ova
image: MSEdge - Win10.ova
file format: raw
virtual size: 6.8G (7255876608 bytes)
disk size: 6.8G

参考資料

https://www.randomhacks.co.uk/how-to-convert-virtualbox-vdi-to-kvm-qcow2/ https://medium.com/@lonardogio/convert-vdi-virtualbox-to-raw-in-windows-c96bded29640

shutdown コマンドについて調べました。

なんとなく使っているshutdown

Ubuntu デスクトップを使っていと、なんとなく、reboot だとか shutdown コマンドを打ち込んでるんですよね。

今すぐシャットダウン

shutdown -h now 

強制シャットダウンをわりと気軽に打ち込んでるんだけど、shutdown コマンドってたしかスケジュールできたよな。と思って調べました

今すぐシャットダウン

shutdown now

今すぐ、再起動

shutdown -r now

15分後にシャットダウン

showdown +15

60 分後に再起動

shutdown -r +60

13:33に再起動

shutdown -r 13:33

キャンセル

さっき再起動って言ったな、やっぱりなし

shutdown -c 

シャットダウンコマンドの他

シャットダウンのコマンドの他に似たような物がある。

halt
reboot 

などコマンドは多数あります。好きなのを使えばいいんだけど、じつは微妙に違うんだけど再起動・シャットダウンする目的であれば、あまり気にせず使える。

最後に起動したのって何時だっけ

uptime を見ればわかるのですが、uptimeの基準になる起動時間最後のshutdown -r を見ることが出来る。

takuya@~$ who -b
         system boot  2020-04-28 18:30

最近どれくらい reboot してるんだ

最近の再起動の履歴を見ることが出来ます。

takuya@:~$ last -x reboot
reboot   system boot  4.19.0-8-amd64   Fri Apr 24 05:13   still running
reboot   system boot  4.19.0-8-amd64   Wed Apr  8 03:15 - 05:12 (16+01:57)
reboot   system boot  4.19.0-8-amd64   Sat Apr  4 18:20 - 03:14 (3+08:54)
reboot   system boot  4.19.0-8-amd64   Thu Mar 26 16:22 - 18:20 (9+01:57)
reboot   system boot  4.19.0-8-amd64   Fri Feb 28 17:38 - 16:22 (26+22:43)
reboot   system boot  4.19.0-8-amd64   Fri Feb 28 17:30 - 17:37  (00:07)
reboot   system boot  4.9.0-11-amd64   Sun Feb  9 06:50 - 17:37 (19+10:46)
reboot   system boot  4.9.0-11-amd64   Sat Feb  8 23:22 - 17:37 (19+18:15)
reboot   system boot  4.9.0-11-amd64   Sat Feb  8 20:33 - 17:37 (19+21:04)
reboot   system boot  4.9.0-11-amd64   Sat Feb  8 18:35 - 17:37 (19+23:02)
reboot   system boot  4.9.0-11-amd64   Sat Feb  8 12:00 - 17:37 (20+05:37)
reboot   system boot  4.9.0-11-amd64   Sat Feb  8 07:22 - 17:37 (20+10:15)
reboot   system boot  4.9.0-11-amd64   Fri Feb  7 21:18 - 17:37 (20+20:19)
reboot   system boot  4.9.0-11-amd64   Fri Feb  7 18:55 - 17:37 (20+22:41)
reboot   system boot  4.9.0-11-amd64   Fri Feb  7 11:41 - 17:37 (21+05:56)

参考資料

apt で v6 を使わせない。IP v4 に限定して、aptを使う設定。

NTT の壊れた閉域IPv6

NTTの壊れたv6を使っていると、IPoEを設定しない限り、外向きの通信ができない。

v6の設定をあれこれ触っていたりすると、v6 で apt 出来たり出来なかったりするので、とたんに不便になる。 まじ困る。

apt がv6 フォールバック待ちで遅い。

ubuntu の apt だとIPv6 で通信できないときに自動的にv4 に切り替わる。でも遅いよね。何が起きてるんだってパニクるので、つながらんときははっきりつながらんほうが良い。

sysctl で ipv6 全般を禁止するのは流石に不便なので、それはしたくない。でもapt とかはv4 に限定して安心したい。

apt を IPv6 を禁止して IPv4 に限定する

apt の設定に、v4 強制の設定が追加されています。これを使うと解決します。

ipv4-only な apt にする。

echo 'Acquire::ForceIPv4 "true";' | sudo tee /etc/apt/apt.conf.d/99force-ipv4

rubyのプロセス起動で、smtpを使わずに、sendmail コマンドでメール送信するとカンタン

ubuntuシステムからメールを送りたい。

メールを送ろうとすると、SMTPをつかって、MIMEエンコードして SMTP over TLSで接続してとあれこれ手順が必要。

その手順をrubygemでインストールして使い方を調べるのも面倒。

ローカルの postfix にリレーさせる。

ubuntu とかサーバーで使ってるとローカルホストに exim4 や postfix くらいは用意していると思うんですよ。するとsendmail コマンドが使えるじゃないですか。

sendmail でメール送信する例。

$ sendmail takuya@example.com
Subject: Hi Hi

hello from test
.

ruby のプロセス open は標準入力を渡すのがとても楽。

ruby はIO周りと列挙周りだけは、本当にガチで便利ですよね。

シンプルなExim4と、シンプルなsendmail、そしてシンプルな ruby open。単純なものを組み合わせてしまう。

#!/usr/bin/env  ruby
#

open("|sendmail -i -t > /dev/null",'w'){|f|

  f.puts 'To:takuya@example.com'
  f.puts 'Subject: Hello from ruby '
  f.puts '  '
  f.puts '  '
  f.puts 'this is sample from ruby stdin'
  f.puts '  '
  f.puts ''
}

gem 何も要らない

gem のインストールの管理が面倒だったり、 bundler といえども、どこにgemを導入しているか GEM_HOMEのLOAD_PATHであれこれ考える必要もない。gem を外すと楽だった。

単純なことは単純にやるのが一番ですよね。

KISS / Keep it simple stupid が大事ですよ。ほんと。凝りだすときりがない。

ローカルホストにpostfix などMTAを導入する例

takuya-1st.hatenablog.jp

macOSに Linux の ip ( iproute ) コマンドを入れてしまうという邪教

mac でも ip / iproute2 コマンドを使いたい。

ついつい、癖で ip route show って打ち込んでしまうんですよ。

旧き良きBSDなんだし ifconfig / netstat を使えばいいんだけど、 netstat -nr って覚えにくいじゃないですか。

iproute のフリをするショートカット集が用意されている

ip コマンドを出来る限り、 mac 用コマンドにWrappingした代替用の関数群が用意されてる。

iproute2mac のインストール

これをいれれば、MacOSでも Linux / Ubuntu の ip コマンドが使える。完璧に一致することは不可能だけど、よく使うシンプルなものであれば問題なく使えそう。

takuya@Desktop$ uname
Darwin # ⇐ mac です
takuya@Desktop$ brew reinstall iproute2mac
==> Reinstalling iproute2mac
==> Downloading https://github.com/brona/iproute2mac/releases/download/v1.2.3/iproute2mac-1.2.3.tar.gz
Already downloaded: /Users/takuya/Library/Caches/Homebrew/downloads/fdb133eaa8f1346a259295ba9aa22ab568e0dd6b6506cafab6891ae6e31fcf84--iproute2mac-1.2.3.tar.gz
🍺  /usr/local/Cellar/iproute2mac/1.2.3: 6 files, 22.5KB, built in 3 seconds

ip コマンドが使えるぞ

takuya@Desktop$ ip a
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    ether f0:18:
    inet 169.254.146.78/16 brd 169.254.255.255 en0

ip route show でルーティングが見れる。

takuya@Desktop$ ip route show
default via 192.168.1.1 dev en0
127.0.0.0/8 via 127.0.0.1 dev lo0
255.255.255.255/32 dev en0  scope link

ip route add も使えるので、ルーティングテーブルについては覚えることが減って楽になる。

公式にも書いてあるとおり、ちゃんと使う。

ただし、所詮は糖衣錠です。子供用のシロップ風邪薬です。なので、BSDのネットワークコマンドと、mac の networksetup コマンド、これらをちゃんと覚えたほうがいいことは間違いない。

For advanced usage use netstat, ifconfig, ndp, arp, route and networksetup directly.

デリケートでデディケートな詳細な操作は、 netstat / ifconfig / ndp / arp / route / networksetup の各種コマンドを使う。

ルートを追加したり削除する。ip を追加したり削除する程度なら 十分に動いていました。

参考資料

https://github.com/brona/iproute2mac

空白を含むパス名を含むコマンド文字列をシェル(bash)で処理する

" program files " のような空白を含むパス名を持ったコマンド全体を、変数に保持しててそれを実行したい時

そのままだと動かない。

## これが実行できない。
cmd='ls ~/Library/Application\ Support/'
$cmd

空白を含むパス名を入れたコマンドを文字列として、それを実行しようとするとエスケープの処理で頭を悩ますことになる。

eval を使う

cmd='ls ~/Library/Application\ Support/'
eval $cmd

または、sh 経由にする

cmd='ls ~/Library/Application\ Support/'
sh -c "$cmd":

参考資料

https://stackoverflow.com/questions/836334/executing-commands-containing-space-in-bash

qemu の仮想マシンのイメージのディスクサイズを変更する。

libvirtkvmでつかうqemu 用マシンのサイズを変更したい

通常のディスクであれば、ddしたイメージファイルのサイズを変えてあげれば済むのだけれど、qcow2 のイメージファイルはsparse ファイルになっています。

なので、仮想マシンから見えるディスクサイズと、実際のディスクサイズが異なります。

qcowのファイルの現在の情報をみる

qcow のファイルが実ファイルサイズと、仮想マシンからみたファイルサイズが異なるSPARSEファイルかどうか、それを確認するには次のようにします。

sudo qemu-img info  test.qcow

qcow のファイルのサイズを拡張する。

可変サイズのファイルを増やしていく時は、次のように、resize と増分を指定します。

qemu-img resize -f qcow2 test.qcow +10G

コマンドは次の通り

qemu-img resize -f タイプ  ファイル名  +増分サイズ

タイプは殆どの場合 qocw2 ですね。

ファイルサイズを縮小する。

逆に縮小するときは、--shrink オプションを付与します。

qemu-img resize --shrink  -f qcow2 test.qcow -1G

ただし、--shrink は削除していくので、データが有るとロストします。ディスクパーティションの後方から削除していくので、後方が空き領域になっている必要があります。gdisk / resize2fs や gpt GPated などで後方を開けてとかないと怖いですね。

実際にやってみる。

試しに、QCOW2 のファイルを作成してみます。

$ qemu-img create -f qcow2 test.qcow 1G
Formatting 'test.qcow', fmt=qcow2 size=1073741824 cluster_size=65536 lazy_refcounts=off refcount_bits=16

作成された仮想マシン用イメージのファイルの情報を確認します。

ホスト上の実ファイルのサイズは196Kで、仮想マシンのディスクとしてのサイズは1.0Gです。スパースファイルです。

$ sudo qemu-img info  test.qcow
image: test.qcow
file format: qcow2
virtual size: 1.0G (1073741824 bytes)
disk size: 196K
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: false
    refcount bits: 16
    corrupt: false

リサイズしてみます。+1Gしてサイズを増大させます。

$ qemu-img resize -f qcow2 test.qcow +1G
Image resized.

確認します。 ちゃんと、2GBになっていて、ホストから見たサイズは200Kになっていることがわかります。

$ qemu-img info  test.qcow
image: test.qcow
file format: qcow2
virtual size: 2.0G (2147483648 bytes)
disk size: 200K
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: false
    refcount bits: 16
    corrupt: false

libguestfs-tools を使う場合 / virt-resize

最近は、仮想マシンのサイズ変更については、いちいち仮想マシン内部で resize2fs や gdisk をしなくてもいいように virt-resize というツールが用意されていて、容易に仮想マシンのディスクイメージを操作できるようになっています。仮想マシン内部でパーティションがどう使われていようとも、ホスト側から操作することができます。LVM化されてても。

この後の作業

リサイズをしたあとに、resize2fs を掛けると思う。resize2fs を掛けるために仮想マシンを起動するのはナンセンスなので、nbd 経由でQcowを直接マウントしてresize2fsすると楽

qcow2をnbd経由で接続する

リサイズは容量不足で起きる→Sparseする

リサイズをするときは、殆どの場合で容量不足や無駄容量の節約である。

スパース(sprase file ) に変換して無駄容量を削減するのも一つの選択肢である

sparseにして容量削減・節約

参考資料

man qemu-img

関連資料

2022-09-04 追記

sparse / resize /nbd はペアになってないと意味がないので記述とリンクを追加

PostgresSQLの基本的な使い方(ユーザ作成・テーブル作成・確認)ー SQL編+psql で結果確認

目次

psqlPostgreSQLの基本的な操作

PostgreSQLの基本的な管理を見ていきます。

基本的な管理はSQLとして psql のプロンプトで行うものを取り扱います。

initdb や createdb dropuser のようなシェルコマンドは今回扱いません。

psql を使う前に。

インストール前に、日本語を扱う場合のポイント。

日本語環境が設定されて無いときは、日本語環境を作っておく。 時刻も日本JSTにしておく。

Debian / ubuntu の例

dpkg-reconfigure locales
dpkg-reconfigure tzdata

日本語環境の設定してからインストールするのが無難。

インストール ( debian )

sudo apt install postgersql  sudo 

psql の対話型シェルの起動

postgres ユーザーが作成されるので、最初の処理は postgresql ユーザーで行う。

root@:~# sudo -u postgres psql

ユーザーの管理。

ユーザーの管理を psql コマンドで行うことができます。postgresql user と role がありますが、歴史的経緯みたいなものだと思っていればいいです。

ユーザーは login role のエイリアスだったはず。

ユーザーの追加削除と確認

ユーザーの一覧は psql\du を使います。 du は display user とでも覚えときましょう。

実行サンプル

postgres ユーザー1つだけが存在します。

postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

ユーザーの追加。

ユーザーの追加は、 SQLCREATE USER を使えば可能です。

CREATE USER "takuya_1st" PASSWORD 'j0qViQjCzQMFfqH7';

シングルクォーテーション`ダブルクォーテーションに注意する!!PSQLは厳密に区別してる。

ユーザ追加サンプル

ユーザーを追加して、結果を確認。一つ増えるのがわかります。

postgres=# CREATE USER "takuya_1st" PASSWORD 'j0qViQjCzQMFfqH7';
postgres=# \du
takuya_1st  |                                                            | {}
 postgres               | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

ユーザーを削除して、結果を確認。

ユーザーの削除は、 SQLDROP USER 文でできます。

DROP USER "takuya_1st" ;

ユーザー削除サンプル

ユーザーを削除して、ユーザー一覧から消えたことがわかります。

postgres=# DROP USER "takuya_1st" ;
postgres=# \du
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

パスワードの変更

パスワードの変更もSQLを使って可能です。

postgres=# ALTER USER postgres  WITH PASSWORD 'rHBrECDNjbWax1IZ';
ALTER ROLE

初期ユーザーの postgres のパスワードを変えてみるなど。

ROLEロール。create user と create role の違い。

postgresql では ユーザのことを role と呼びます。 LOGIN できるロールのことをユーザーと呼ぶ。と覚えてください。 歴史的経緯によるとでも思っておけばいいと思います。UNIXのユーザーようにPostgreSQLのユーザーはグループをもっていて、グループにロールで管理されています。1つのデータベースのインスタンスを多数のクライアントで共有していた名残りでしょう。個人でデータベースを作る、個人でプログラムから使うときなど、はあまり気にしなくていいと思います。

ロールの作成と確認

これは、create user と同じ

CREATE ROLE "outline_Admin" PASSWORD '01UNeD86gwVmRDRG';

データベースを作成する

日本語UTF-8に対応したテンプレートを作る。

シェル環境変数が LANG=ja_JP.UTF-8なら自動で作られるのだけど。作られていないとUTF-8でも行けそうなん。 気持ち悪いなら、日本語対応したテンプレートを作っておくといいかもしれない。

CREATE DATABASE template1 LC_COLLATE 'ja_JP.UTF-8' LC_CTYPE 'ja_JP.UTF-8' ENCODING 'UTF8' TEMPLATE template0;
CREATE DATABASE template2 LC_COLLATE 'ja_JP.UTF-8' LC_CTYPE 'ja_JP.UTF-8' ENCODING 'UTF8' TEMPLATE template0;
UPDATE pg_database SET datistemplate = true where datname = 'template2';

データベースの一覧

対話プロンプト psql のコマンドで \l でデータベースの一覧を見れます。 List database の L(エル)と覚えておけばいいでしょう。

postgres=# \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres

ここで出てくる template は言語ごとのCollationが設定されたテンプレートです。debian/ubuntu の場合 LANG=ja_JP.UTF-8bashから apt install postgres すると postgres のaptインストールスクリプトで自動生成されます。

データベースの切替え

データベースを切り替えるにはつぎのように psql コマンド \c で可能です。

\c databae_name

これは、mysql の use DATABASENAME に相当する。

実行サンプル

切り替えたときのサンプル。プロンプトが変わるのでわかる。

postgres=# \c outline
You are now connected to database "outline" as user "postgres".
outline=# \q

データベースを作成。

SQLでデータベースを作成することができます。

CREATE DATABASE my_database;

データベースの作成サンプル

outline という名前でデータベースを作って一覧を見てみます。

postgres=# create database outline;
CREATE DATABASE
postgres=# \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 outline   | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres

データベースを削除する

SQL 構文でデータベースを削除することができます。

DROP DATABASE my_database;

実行サンプル

outline という名前のデータベースを削除し、一覧を見てみます。

postgres=# drop database outline;
DROP DATABASE
postgres=# \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres

オーナー指定してデータベースを作る

SQLでデータベースを作るときに所有者(オーナー)を指定して作ることができます。

CREATE DATABASE takuya_database  OWNER "takuya";

これは非常によく使います。

実行サンプル

ユーザーを作成し、続けてそのユーザーのデータベースを作成します。

postgres=# CREATE USER "outline_Admin" PASSWORD 'kj4zzkvVXuU7MlSL';
CREATE ROLE
postgres=# create database outline owner "outline_Admin";
CREATE DATABASE
postgres=# \l
                                         List of databases
   Name    |         Owner          | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+------------------------+----------+-------------+-------------+-----------------------
 outline   | outline_Admin | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 postgres  | postgres               | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres               | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |                        |          |             |             | postgres=CTc/postgres
 template1 | postgres               | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |                        |          |             |             | postgres=CTc/postgres

データベース作成時:文字コードを指定

文字コードを指定してつくると便利です。 テンプレートを使って作る事が多いです。

CREATE DATABASE outline  LC_COLLATE 'ja_JP.UTF-8' LC_CTYPE 'ja_JP.UTF-8' ENCODING 'UTF8' 
CREATE DATABASE outline  LC_COLLATE 'ja_JP.UTF-8' LC_CTYPE 'ja_JP.UTF-8' ENCODING 'UTF8' TEMPLATE template0;

template が en_US だし困ったなぁってときに、日本語でDBを作成しておくとトラブルが減る*1

実行サンプル

オーナー指定とテンプレート指定、文字コード指定を「全部合わせ」てデータベースを作成している例です。

CREATE DATABASE outline owner "outline_Admin"  LC_COLLATE 'ja_JP.UTF-8' LC_CTYPE 'ja_JP.UTF-8' ENCODING 'UTF8' TEMPLATE template0;

postgres=# \l
                                         List of databases
   Name    |         Owner          | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+------------------------+----------+-------------+-------------+-----------------------
 outline   | outline_Admin | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 |
 postgres  | postgres               | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 repost    | repost                 | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres               | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |                        |          |             |             | postgres=CTc/postgres
 template1 | postgres               | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |                        |          |             |             | postgres=CTc/postgres
(5 rows)

おさらい psql コマンド

データベースの切り替え

postgres=#  \c outline
### データベースの一覧
postgres=#  \l
### ユーザー一覧
postgres=# \du

おさらい SQL での管理。

# ユーザー作成
 CREATE USER "takuya_1st" PASSWORD 'j0qViQjCzQMFfqH7';

## パスワード変更
ALTER USER postgres  WITH PASSWORD 'rHBrECDNjbWax1IZ';

# データベース作成
CREATE DATABASE takuya_database ;
CREATE DATABASE takuya_database  OWNER "takuya";
CREATE DATABASE outline  owner "takuya" LC_COLLATE 'ja_JP.UTF-8' LC_CTYPE 'ja_JP.UTF-8' ENCODING 'UTF8' 

2020-07-19

更新

*1: 個人の感想です。

ディレクトリの中のファイルを「時刻」でソートする find と lsをつかって、最新のファイルだけを取り出す。

ls コマンドの場合

ls -t | head -n1

ls コマンドで、時刻順に並べることができるので、これを head と組み合わせれば出来る。

takuya@Gitlab:~$ sudo ls -lt  /var/opt/gitlab/backups/
total 92268132
-rw------- 1 git    git    43629199360 Apr 25 02:20 1587748340_2020_04_25_12.9.2_gitlab_backup.tar
drwx------ 7 git    git           4096 Apr  4 03:40 tmp
-rw-r--r-- 1 takuya takuya 47202314240 Apr  4 02:17 1585836147_2020_04_02_12.9.2_gitlab_backup.tar
-rw------- 1 git    git     3651025200 Apr  3 22:25 registry.tar.gz

ただし、取り出せるのは「basename」のファイル名です。

サンプル

takuya@Gitlab:~$ sudo ls -t  /var/opt/gitlab/backups/  | head -n 1
1587748340_2020_04_25_12.9.2_gitlab_backup.tar

find コマンドでやる場合

find コマンドでもできます。

最新の1件だけを取り出すには、head と組み合わせれば大丈夫かな。

find  /var/opt/gitlab/backups/ -type f  -printf "%T@ %p\n" | sort -nr| head -n 1

動作の原理について

find コマンドには printf のオプションがあって、これを使ってsort してあげれば、カンタンに実現できます。

takuya@Gitlab:~$ sudo find  /var/opt/gitlab/backups/ -type f  -printf "%T@ %Tc %p\n" | sort -nr
[sudo] password for takuya:
1587748816.6963751750 Sat Apr 25 02:20:16 2020 /var/opt/gitlab/backups/1587748340_2020_04_25_12.9.2_gitlab_backup.tar
1585934261.3147121750 Sat Apr  4 02:17:41 2020 /var/opt/gitlab/backups/1585836147_2020_04_02_12.9.2_gitlab_backup.tar
1585920302.0000000000 Fri Apr  3 22:25:02 2020 /var/opt/gitlab/backups/registry.tar.gz

find の場合は、パス名で返ってくる。 パスで取れるのは、ls に比べて便利かもしれない。

最新ファイルのフルパスがほしいときは、 find の引数にフルパスを入れてあげればいいのだから。

動作サンプル

takuya@Gitlab:~$ sudo find  /var/opt/gitlab/backups/ -type f  -printf "%T@ %p\n" | sort -nr| head -n 1 | cut -d' ' -f2
/var/opt/gitlab/backups/1587748340_2020_04_25_12.9.2_gitlab_backup.tar

参考資料

https://superuser.com/questions/294161/unix-linux-find-and-sort-by-date-modified

systemd タイマーの書き方。OnCalendarのtimer 設定の記述方法とチェック方法をおさらいする。cronの代替にするサンプル集

systemd の timer サービスの書き方で時間の指定が困る。

cron で日付や時間の指定をようやく覚えて自由自在に作ってたのに、systemd timer だと onCalendar です。crontabから覚え直しです。

cron書式と違うんですよね。onCalendarは独自です。

systemd.timer の例

OnCalendarは次のように timer ファイル使いますよね。

[Unit]
Description=Splattoon splatnet2ink timer

[Timer]
OnCalendar= hourly
RandomizedDelaySec=10
Unit = splatnet2statink.service

[Install]
WantedBy=default.target

関連記事 →  splatnet2statinkで stat.inkへアップロードをsystemd で自動化する。 - それマグで!

OnCalendar の書式

書式は次のようになっています。

OnCalendar=$DAY_OF_WEEK $YEAR-$MONTH-$DAY $Hour:$Minute:$Second

ただし、省略可能だったりするので、世間にはいっぱい書式が溢れている。

全部詳細なのは、公式ドキュメントを読んだほうが良いと思う

記述例

書式例のサンプルとか、作成方法を見たほうが早い

よく使いそうなもの

サンプル
毎週月曜 mon
毎週月水金 mon,fri,wed
毎日18時 18:00
毎木 15時 Thu 15:00

フルで書いた書式

サンプル
毎週月曜 Mon *-*-* 00:00:00
毎週月水金 Mon,Wed,Fri *-*-* 00:00:00
毎日18時 *-*-* 18:00:00
毎木 15時 Thu *-*-* 15:00:00

省略形のほうが読みやすいし、一瞥して理解しやすい。ただし、記述が面倒な感じありますね。

月末はちょっと特殊

特殊記号 チルダ ~ を使って月末から何日か計算する

サンプル
月最終日 *-*~1 18:*
月末2日前 *-*~2 18:*
5月最終火曜 Tue *-*~07
最終月曜日 mon *-*~07/1

最終曜日、これは最終日から -7を取得して、曜日 絞り込んでる、これで最終月曜日などを計算する。ハイフンは使えないので、代わりにチルダって覚えると良いです。

毎月の最終金曜日とか業務に使えそうですよねー

ただし、毎月25日だとか26日だとかは、祝日の計算が入ってくるので、細かいところはプログラムでやるしか無いですよね。

定期的書式

省略形の 定期系書式

onCalendar 同等のフル書式 日本語での意味
minutely *-*-* *:*:00 毎分
hourly *-*-* *:00:00 毎時
daily *-*-* 00:00:00 日次
monthly *-*-01 00:00:00 月次
weekly Mon *-*-* 00:00:00 週次
yearly *-01-01 00:00:00 年次
quarterly *-01,04,07,10-01 00:00:00 四半期ごと
semiannually *-01,07-01 00:00:00 半期ごと

書式を調べる方法 systemd-analyze calendar

省略形や、サンプルで書式をアレコレと試行錯誤するために、テストツールがあります。

このコマンドで書式が正しいか調べることができます。

systemd-analyze calendar 'Thu 15:00'

systemd でタイマーを作って、書式がおかしいとエラーになったときに役に立つコマンドです。

たとえば、次のようなうろ覚えの省略形を試すと、解析されて結果が取れます。

誤ったOnCalendar記述の例

エラーになることがわかります。どうすれば良いのかの提案はありません。

takuya@:~$ systemd-analyze calendar 'Thu 15'
Failed to parse calendar specification 'Thu 15': 無効な引数です

正しい記述の例

正しく記述できると、フル書式ではどう書くのか、また、次に実行される時刻を押してくれます。

takuya@:~$ systemd-analyze calendar 'Thu 15:00'
  Original form: Thu 15:00
Normalized form: Thu *-*-* 15:00:00
    Next elapse: Thu 2020-04-30 15:00:00 JST
       (in UTC): Thu 2020-04-30 06:00:00 UTC
       From now: 6 days left

日付のチェックが出来るところがとても有能だと思います。crontab / cron だと日付のチェックが面倒だし。

まとめ

OnCalendar は DOW Y-M-D H:i:S でかく。
OnCalendar は systemd-analyze calendar で省略形の書式試す。

関連記事

systemd の タイマーは enable してもstart をしないと動かない - それマグで!
splatnet2statinkで stat.inkへアップロードをsystemd で自動化する。 - それマグで!

参考資料

https://wiki.archlinux.org/index.php/Systemd/Timers

systemd.time

splatnet2statinkで stat.inkへアップロードをsystemd で自動化する。

splatnet2statink で戦績を保存したい。

かれこれ2ヶ月くらいスプラトゥーン2から離れている takuya ですこんばんは。

2020年のコロナウイルス感染症騒動で、ちょっと暇になってしまったので、スプラトゥーンを復活しようと思っています。リングフィットアドベンチャーも届いたのですが、スプラトゥーンには中毒性があって面白いですよね。

しばらく使ってなかったので iksm_sessionが切れてしまってので、再発行と自動取得をまとめてsystemd で作り直します。

戦績を保存する。

splatnet2statinkを使って、戦績をstat.inkに保存していきます。

ソースコードの取得

ソースコードを取ってきます。

git clone git@github.com:frozenpandaman/splatnet2statink.git
cd splatnet2statink

これでsplatoon2 のデータを扱えます。

python の環境を作ります。

最初に pipenv 環境を作ります。 pipenv 環境がない場合は pythonとpip を用意して pip install pipenvをしておきます。

cd splatnet2statink

export PIPENV_VENV_IN_PROJECT=1
pipenv install 
pipenv shell 

pipenv 環境下で作業をします。

最初に依存モジュールを用意しておきます。

(splatnet2statink) pip install -r requirements.txt

セッションキーを用意します。

初回起動でセッションキーを登録します。

stat.ink のセッションキーを用意しておいて、初回起動で登録します。

(splatnet2statink) ./splatnet2statink.py
splatnet2statink v1.5.4
Generating new config file.
stat.ink API key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Default locale is en-US. Press Enter to accept, or enter your own (see readme for list).
ja-JP
Pulling data from online...
Blank cookie.

続けて、iksm_session を取り出します。

httpsから始まる URLが表示されるので、これを MacOS Safariに貼り付けます。 (最新版の Chromeではリダイレクト先がローカルになるのでエラーになりました。)

Make sure you have fully read the "Cookie generation" section of the readme before proceeding. To manually input a cookie instead, enter "skip" at the prompt below.

Navigate to this URL in your browser:
https://accounts.nintendo.com/connect/1.0.0/authorize?state=XXXXXXXXXXXXXXXXXXXXe_challenge_method=S256&theme=login_form

Log in, right click the "Select this account" button, copy the link address, and paste it below:

Safariでログインして アドレスをコピー

アドレスをコピーして コンソールに貼り付けます。

PCならリンクを右クリック

貼り付けたらアップロードが始まる。

config.txt が作成されて アップロードが出来るようになる。

Log in, right click the "Select this account" button, copy the link address, and paste it below:
npf71b963c1b7b6d119:/XXXXXXXXXXXXXXXXXXXXXXXXyTTNw-B

Wrote session_token to config.txt.
Attempting to generate new cookie...
Wrote iksm_session cookie for たくや to config.txt.

config.txt は重要

config.txtに保存されたセッションキーで認証しているので、config.txtをバックアップしておく。

systemd に登録する。

systemd で定期的に、splatoon2 の戦歴とサーモンランの履歴を取り出して保存します。

サービスファイル splatnet2ink.service ファイルを作成

モニタリングを起動して放置していると、なぜだか上手くイカないので、1時間に一回起動して戦歴をチェックする。

ガチマッチもレギュラーマッチもどう頑張っても1時間に50件の保存上限を超えるプレイをできないので、これでいける *1

[Unit]
Description=Splattoon splatnet2ink

[Service]
WorkingDirectory=/home/takuya/.splatnet2statink
ExecStartPre=/home/takuya/.splatnet2statink/.venv/bin/python /home/takuya/.splatnet2statink/.venv/bin/pip install --upgrade pip
ExecStartPre=/home/takuya/.splatnet2statink/.venv/bin/python /home/takuya/.splatnet2statink/.venv/bin/pip install --upgrade -r  /home/takuya/.splatnet2statink/requirements.txt
ExecStartPre=/usr/bin/git pull
ExecStart=/home/takuya/.splatnet2statink/.venv/bin/python    /home/takuya/.splatnet2statink/splatnet2statink.py -r
ExecStartPost=/home/takuya/.splatnet2statink/.venv/bin/python    /home/takuya/.splatnet2statink/splatnet2statink.py -r --salmon

#Restart=always
#RuntimeMaxSec=600
; User=takuya
; Group=takuya
[Install]
WantedBy=default.target

タイマーファイル splatnet2ink.timerを作成しておく

[Unit]
Description=Splattoon splatnet2ink timer

[Timer]
OnCalendar= hourly
RandomizedDelaySec=10
Unit = splatnet2statink.service

[Install]
WantedBy=default.target

systemd に登録する。(ユーザーごとの systemd )

ユーザー空間なら、次のところにファイルを作って起動する。

mkdir -p ~/.config/systemd/user/
## または
mkdir -p /etc/systemd/user/

systemdをリロードして unit を登録

systemctl --user daemon-reload

起動してチェック

systemctl --user start splatnet2statink.service
systemctl --user status splatnet2statink.service
systemctl --user start splatnet2statink.timer
systemctl --user status splatnet2statink.service

有効化

systemctl --user enable splatnet2statink.service
systemctl --user enable splatnet2statink.timer

戦歴があるとモチベーション維持に良い。

戦歴をずっと眺めることで、反省点がわかる。

なにより成績が向上しているとモチベーションアップに役立つ。

動画を撮影したりすると動画撮影の検索インデックスとしても使える。便利。

2022-07-20

splatoon のika log の更新は、毎日起動してないと、数日でセッションが切れてしまうので注意。

参考資料

イカ参考資料です。

ユーザー毎の systemd を使ってシステム全体設定と個人用設定を分ける。 - それマグで!

https://github.com/frozenpandaman/splatnet2statink#cookie-generation

https://tkgstrator.work/?p=26857

【簡易版】Windowsだけでsplatnet2statinkを使ってスプラトゥーン2の戦績をstat.inkに自動で登録する【導入/利用編】 – バニラソルト

*1: 複数台のニンテンドースイッチで同一アカウントでプレイしない限り大丈夫

指定したファイルが存在するフォルダを指定する

画像が入ったフォルダを取り出したい。

Nextcloud を触っていて、画像が散らばってしまった。なので、画像大量に入ったフォルダを調べることにする。

となると、どんな方法が良いか思案したが、一番手っ取り早いのは find コマンドだろう

find コマンドでjpg が含まれるフォルダを探す

find してさらに find する感じにしてみた。

#!/usr/bin/env bash

IFS=$'\n'
for i in $( \find .  -mindepth 1 -maxdepth 1  -type d ) ; do
  [[ $( \find $i -type f -iname '*.jpg' | wc -l  ) == 0 ]] && continue;
  echo $i;
done

たくさん画像があるフォルダを探す。

条件をちょっと変えれば、100枚以上の画像があるフォルダを探すってのもできるね。

#!/usr/bin/env bash

IFS=$'\n'
for i in $( \find .  -mindepth 1 -maxdepth 1  -type d ) ; do
  [[ $( \find $i -type f -iname '*.jpg' | wc -l  ) == 100 ]] && continue;
  echo $i;
done

もっといい方法がありそうなんだが、ぱっと思いつかなかった。 GNU コマンドなら --include 等があるからできそうな気もするんだけど。

LXC・LXD のコンテナのポートを外部に公開する docker expose的なやつ

lxc で外部にポートを公開する。

docker だと expose で手軽にできるんだけど、LXCだとiptables使えとか forwarding しろとかめんどくさいので、もっと簡単にポート転送できるものがないか調べた。

プロキシで飛ばせる

たとえば、nginx-container があって、ホスト側のIPを内部にそのまま出すには。

lxc config device add nginx-container my-https proxy  listen=tcp:192.168.12.10:443 connect=tcp:10.185.93.215:443 bind=host
lxc config device add nginx-container my-http proxy  listen=tcp:192.168.12.10:80 connect=tcp:10.185.93.215:80 bind=host

簡単な図解

クライアント 
 →Lxc ホスト 192.168.12.10:80 (転送
   → Lxcゲスト  10.185.93.215:80

追加するときは

lxc config device add $LXC_CONTAINER_NAME $PROXY_DEVICE_NAME proxy  \
   listen=tcp:$LXC_HOST_IP:$LXC_HOST_PORT \
   connect=tcp:$LXC_CONTAINER_IP:$LXC_CONTAINER_PORT bind=host

削除するときは

lxc config device remove $LXC_CONTAINER_NAME $PROXY_DEVICE_NAME

設定の確認

lxc config show nginx-container

これで設定されているプロキシ転送を確認することが出来る。もうすこし楽ちんでも良さそうなものだが。

lxc config proxy お手軽。

proxy で nginx のコンテナを作ってポート転送しておけば、LXCの内部側にいくらでもサービス用にコンテナを起動できて便利。

macvlan や bridge で共有してると、だんだんIPやポートが膨大になってきて頭がおかしくなりそうなので、nginx で一旦中継しちゃうのが便利。

nginx は、比較的なんでも転送できるので、sshpostfix などでも転送できるでちょっとしたルーター代わりにあげておくと便利。

一点だけ問題がある。

lxc のプロキシ設定は、プロキシ先を「IP」で指定しなくちゃいけない。lxc 自体が再起動して、IPが変わると動作しなくなることがあるので注意。

IPが不意に変わることが在り、大混乱を発生させるので、まじで注意。

参考資料

https://hnakamur.github.io/blog/2018/07/05/port-forwarding-using-lxd-proxy/

2020-12-30 更新

削除する方法も併せて書いた

libvirt + qemue の kvm 仮想マシンで画面を持たないコンソールのVMをぱぱっと作成して コンテナみたいに使う

VMがヘビィだ

docker とか LXC 使ってると、VMがヘビィに感じることがある。もっと手軽に仮想マシンを使いたいななどと思う。

UbuntuDebian仮想マシンで新規で作って、コンソールでテキストで扱えれば嬉しいわけです。

SSH経由で、VMを作成

SSHのテキストベースで、仮想マシンを作成し、そのまま コンソールでインストールするコマンド

virt-install というコマンドでぱぱっとVMを作成して、そのままインストールを開始できる。

ubuntu の場合

virt-install \
--name ubuntuLTS \
--ram 30029 \
--disk path=/var/lib/libvirt/images/ubuntu-1910.qcow2 \
--vcpus 4 \
--virt-type kvm \
--os-type linux \
--os-variant ubuntu18.04 \
--graphics none \
--location 'http://archive.ubuntu.com/ubuntu/dists/bionic/main/installer-amd64/' \
--extra-args "console=tty0 console=ttyS0,115200n8"

debian の場合

debian ならこんな感じだろうか。

virt-install \
--name ubuntuLTS \
--ram 30029 \
--disk path=/var/lib/libvirt/images/debian10.qcow2 \
--vcpus 4 \
--virt-type kvm \
--os-type linux \
--os-variant debian10 \
--graphics none \
--location http://ftp.kddilabs.jp/pub/Linux/distributions/Debian/debian/dists/buster/main/installer-amd64/ \
--extra-args "console=tty0 console=ttyS0,115200n8"

インストール画面はSSH経由で

SSHCLIでテキストでインストールで切るので便利。

f:id:takuya_1st:20200401075852p:plain

f:id:takuya_1st:20200401081159p:plain

tasksel で openssh-server を選ぶのを忘れないように

インストール時に、openssh-server を選ばないと、ログインできなくて詰みます。もちろんネットワーク設定が必須です。無いと詰み。

grub を無理やり変更すれば可能だけどめんどくさいので、 openssh-server のインストールを忘れないように。

インストール後に grub を編集します。

シリアル コンソール を使えるように、 grub を設定しておきます。

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
##
GRUB_CMDLINE_LINUX="console=tty1 console=ttyS0,115200"
GRUB_TERMINAL="console serial"
GRUB_SERIAL_COMMAND="serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1"

grub を更新しします。

sudo update-grub

これで、virsh からコンソールアクセスができる

virsh console ubuntu-vm

または

virsh
console ubuntu-vm

でコンソールでログインができるようになる。VGA関連をバッサリ削れるのでだいぶ手軽に使えるようになる。

f:id:takuya_1st:20200401133345p:plain

その他の方法

似たような方法でも、同じような目的を達成する事ができます。

Ubuntuクラウド イメージ vmx Debian のクラウド イメージ qcow LXC /docker など

これらを使えば、コンソールで起動するVMを確保することができる。

軽量なコンテナでも良いんだけどVMが良いというときなど、TPOに合わせて使い分けていきたい。 何でもかんでもDockerが最高というわけでもないので

参考資料

Creating Virtual Machines on KVM with virt-install

https://cloud.debian.org/images/cloud/

lxc でコンテナへファイルを送信(コピー)する。

lxc で ホストからコンテナへファイルを送信する。

LXC は lxc の file コマンドでファイルをコピーすることができる。

takuya@:~$ lxc file push ~/.vimrc  ${CONTAINER}/root/

ただし! 末尾の スラッシュを除外すると面倒になるので注意。

takuya@:~$ lxc file push .vimrc  ${CONTAINER}/root
Error: Path already exists as a directory: File too large

/root の中にコピーしようと思うと、末尾のスラッシュを入れないと、ファイル名として解釈されてしまう。

すごくオペレーションミスになりやすいので注意。