BioErrorLog Tech Blog

試行錯誤の記録

Ubuntuの鶴の壁紙の詳細を調べる

Ubuntuに入っている綺麗な鶴の壁紙の詳細を追います。

はじめに

Ubuntuの鶴の壁紙

このUbuntuの鶴の壁紙、綺麗で面白い、いい雰囲気ですね。

詳細が気になったので調べてまとめます。


※ 以前調べたときの下記メモをもとに再整理したものです。

Ubuntuの鶴の壁紙の詳細を調べる

画像ファイルを調べる

Ubuntu上に保存されている壁紙画像ファイルを見てみます。

調べてみると、デフォルト壁紙ファイルたちは /usr/share/backgrounds に配置されているとのこと。

そこを見てみると確かに壁紙ファイルが配置されています。

Ubuntuのデフォルト壁紙ファイル

少し眺めてみると、多くのファイル名は<壁紙名>_by_<作者名>のフォーマットで記載されていることがわかります。

しかし、例の鶴の壁紙のファイル名はhardy_wallpaper_uhd.png

作者名も記載されてないし、意味もいまいち分かりません。

この絵が作られた場所

ファイル名から直接的な情報は得られませんでしたが、このファイル名を頼りに検索をかけてみます。

少し探してみると、Ubuntuのwikiページがヒットしました。

Artwork/Incoming/Hardy/Alternate/Fela_Kuti - Ubuntu Wiki

まさにここで、この絵の原型が提案され、議論され、コミュニティの中で改善が提案されていく様子が残っています。

誰かが一人で完結して描いたものではなく、コミュニティー全体で作られていたんですね。 まさにLinuxの思想という感じがします。

壁紙について議論・改善案の提案がコミュニティーで繰り返される様子

この絵のタイトル

この絵のタイトルは、

Fela Kuti
A Fela Kuti inspired heron.

だそうです。

"サギをイメージしたFela Kuti"

といったところでしょうか。

この鳥、鶴ではなくサギだったみたいですね。
(そもそもこの形状の鳥を見て鶴を想起するのは日本人だけか)

"Fela Kuti"の方は、検索してみるとミュージシャンばかりがヒットします。 この絵とミュージシャンFela Kutiが関係あるのか、はたまた全然関係ないのか、ちょっとわかりませんでした。

ミュージシャン"Fela Kuti" | 画像はWikipediaより引用

元データで遊ぶ

下記のページには各バージョンのソースデータが置かれているので、少し触ってみます。

attachment:source.svg of Artwork/Incoming/Hardy/Alternate/Fela_Kuti - Ubuntu Wiki

これもなかなか面白いです。

背景の模様も面白いなあと思って見てましたが、これらは拡大したサギ自身でした。

壁紙のソースデータ. 背景の模様も拡大したサギ自身だった


なお、svgファイルで配られているので、自分でも簡単に色や配置を変えることができます。

最後に自分でいじってみたバージョンを貼って、この調査を終わろうと思います。

ソースデータをいじって自分でアレンジしてみたver

おわりに

以上、Ubuntuの鶴(サギ)の壁紙の詳細を追いかけました。

同じく気になった方がもしいれば、参考にしていただけると幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

Artwork/Incoming/Hardy/Alternate/Fela_Kuti - Ubuntu Wiki

attachment:source.svg of Artwork/Incoming/Hardy/Alternate/Fela_Kuti - Ubuntu Wiki

Where are the Unity desktop wallpapers located? - Ask Ubuntu

Fela Kuti - Wikipedia

ファイル名をコマンドで一括変更する | Linux

renameコマンドでできます。

はじめに

aaa-1.txt
aaa-2.txt
aaa-3.txt

このようなファイルがあったときに、

bbb-1.txt
bbb-2.txt
bbb-3.txt

のようなファイル名に、CLIコマンドで一括変更したい。

やり方の備忘録です。

# 作業環境: Amazon Linux 2023
$ cat /etc/*release
Amazon Linux release 2023 (Amazon Linux)
NAME="Amazon Linux"
VERSION="2023"

renameコマンド

renameコマンドを使えば、ファイル名の一括変更が可能です。

コマンドのmanページ:
rename(1) - Linux manual page

基本的な使い方

基本的な使い方はこちら:

rename <置換対象の文字列表現> <置換後の文字列> <ファイル名>...

ここで<置換対象の文字列表現><ファイル名>にはワイルドカードを使うことも可能です。


そのほかオプション情報を含めたhelp情報も置いておきます:

$ rename --help

Usage:
 rename [options] <expression> <replacement> <file>...

Rename files.

Options:
 -v, --verbose       explain what is being done
 -s, --symlink       act on the target of symlinks
 -n, --no-act        do not make any changes
 -o, --no-overwrite  don't overwrite existing files
 -i, --interactive   prompt before overwrite

 -h, --help          display this help
 -V, --version       display version

For more details see rename(1).

ファイル名を一括変更する

では実際にファイル名を一括変更します。

現在下記のようなファイルがあります。

$ ls
aaa-1.txt  aaa-2.txt  aaa-3.txt

このファイル名のaaa部分をbbbに一括変更するには、次のコマンドを実行します。

# rename <置換対象の文字列表現> <置換後の文字列> <ファイル名>
rename aaa bbb aaa-*.txt

実行後、期待通りファイル名が一括変更されました。

$ ls
bbb-1.txt  bbb-2.txt  bbb-3.txt

おわりに

以上、Linuxでファイル名をコマンド一括変更するちょっとした備忘録でした。

どなたかの参考になれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

参考

rename(1) - Linux manual page

Raspberry PiでPyTorchがIllegal instructionエラーを起こす事象の対処法

Raspberry Pi 4でPyTorch2.0が下記エラーを出す事象の解決策をメモします。

Illegal instruction

はじめに

最近、Raspberry PiとChatGPTを組み合わせて何か面白いことができないだろうか、とあれこれ実験しています。

そんな中、Raspberry PiでPyTorch2.0.0(記事執筆時の最新バージョン)をインストールしたところ、import torchしただけでIllegal instructionのエラーが出る事象に遭遇しました。

状況と取り急ぎの対処をメモします。

Raspberry PiでPyTorchがIllegal instruction

起きた事象

PyTorch2.0.0をpip installしてimport torchすると、Illegal instructionのエラーが出る。

pip install torch==2.0.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
python -c "import torch;print(torch.__version__)"
# Illegal instruction


環境: Raspberry Pi 4 Model B 4GB RAM / 64bit Raspberry Pi OS(bullseye)

$ hostnamectl
   Static hostname: raspberrypi
         Icon name: computer
        Machine ID: 4f8b19cb3280458c99d89xxxxxx
           Boot ID: 275f81g1c1fd4249a49bbxxxxxx
  Operating System: Debian GNU/Linux 11 (bullseye)
            Kernel: Linux 6.1.19-v8+
      Architecture: arm64

対処法

根本解決ではありませんが、PyTorchバージョンを1.13.1に戻せば解消します。

pip install torch==1.13.1 torchvision==0.14.1 torchaudio==0.13.1 --index-url https://download.pytorch.org/whl/cpu
python -c "import torch;print(torch.__version__)"
# 1.13.1

原因はPyTorch最新バージョン2.0.0とRaspberry PiのCPUアーキテクチャの相性の問題だと思いますが、下記のissueでも未だ議論は決着していません。

Illegal instruction (core dumped) : PyTorch 2.0 on Raspberry Pi 4.0 8gb · Issue #97226 · pytorch/pytorch · GitHub

バージョンを戻せば解消する、という元も子もない話ですが、逆にその他もろもろの足掻きでは解消できなかった事例、と受け取ってもらえれば幸いです。

おわりに

バージョンを戻さないと解決しなかった、というただの懺悔のような話になってしまいました。

今後のversionで解決されるのを祈っています。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

Illegal instruction (core dumped) : PyTorch 2.0 on Raspberry Pi 4.0 8gb · Issue #97226 · pytorch/pytorch · GitHub

Illegal instruction (core dumped) on Raspberry Pi 4B · Issue #8 · KumaTea/pytorch-aarch64 · GitHub

terraform plan結果の要約を表示するワンライナー

terraform plan実行時に、plan結果と要約を併せて表示するワンライナーを組みます。

はじめに

terraform plan結果は往々にして長くなってしまい、全てチェックするのが辛くなりがちです。

plan結果の出力を簡潔にするようなコマンドオプションも現段階では提供されていません: concise mode for `terraform plan` · Issue #10507 · hashicorp/terraform · GitHub

そこで今回は、terraform plan結果を要約して表示するワンライナーを組んでいきます。

もっとマシなやり方がある場合はぜひ教えてください。

terraform plan結果の要約を表示する

シンプルな解決策から順に複雑なものに発展させていきます。

※作業環境:

terraform --version
# Terraform v1.3.4
# on linux_amd64

lsb_release -a
# Distributor ID:  Ubuntu
# Description: Ubuntu 22.04.1 LTS
# Release: 22.04
# Codename:    jammy

1. とりあえずgrep

terraform plan | grep -E '#|Plan:'

plan結果のうち、要点となる情報が含まれる#と最終行のPlan: XX to add, X to change, X to destroy.を抽出します。

要点だけ見たいときはこれでも十分使えますね。


出力例:

$ terraform plan | grep -E '#|Plan:'
  # module.lambda_rust.data.archive_file.zip will be read during apply
  # (depends on a resource or a module with changes pending)
  # module.lambda_rust.aws_cloudwatch_event_rule.this[0] will be created
  # module.lambda_rust.aws_cloudwatch_event_target.this[0] will be created
  # module.lambda_rust.aws_cloudwatch_log_group.this will be created
  # module.lambda_rust.aws_iam_policy.lambda_logging will be created
  # module.lambda_rust.aws_iam_policy.trigger_lambda will be created
  # module.lambda_rust.aws_iam_role.this will be created
  # module.lambda_rust.aws_iam_role_policy_attachment.this["demo_lambda_logging"] will be created
  # module.lambda_rust.aws_lambda_function.this will be created
  # module.lambda_rust.aws_lambda_permission.allow_cloudwatch[0] will be created
  # module.lambda_rust.null_resource.rust_build will be created
Plan: 10 to add, 0 to change, 0 to destroy.

2. 元々の出力も表示する

上のやり方だと元々の詳細な出力は見れません。 要約表示と元の出力の両方を見たいところです。

とりあえずteeで出力を分岐させ、プロセス置換を利用してgrep要約を適当なtmpファイルに出力させて表示してみます:

terraform plan | tee >(grep -E '#|Plan:' > /tmp/_plan_abst.log) && cat /tmp/_plan_abst.log

これで、plan実行したときはまず従来の結果を出力し、処理が終了したら要約が表示されるようになります。


出力例:

$ terraform plan | tee >(grep -E '#|Plan:' > /tmp/_plan_abst.log) && cat /tmp/_plan_abst.log

## 中略:従来のplan結果表示

  # module.lambda_rust.null_resource.rust_build will be created
  + resource "null_resource" "rust_build" {
      + id       = (known after apply)
      + triggers = {
          + "code_diff" = ""
        }
    }

Plan: 10 to add, 0 to change, 0 to destroy.

─────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't
guarantee to take exactly these actions if you run "terraform apply" now.
  # module.lambda_rust.data.archive_file.zip will be read during apply
  # (depends on a resource or a module with changes pending)
  # module.lambda_rust.aws_cloudwatch_event_rule.this[0] will be created
  # module.lambda_rust.aws_cloudwatch_event_target.this[0] will be created
  # module.lambda_rust.aws_cloudwatch_log_group.this will be created
  # module.lambda_rust.aws_iam_policy.lambda_logging will be created
  # module.lambda_rust.aws_iam_policy.trigger_lambda will be created
  # module.lambda_rust.aws_iam_role.this will be created
  # module.lambda_rust.aws_iam_role_policy_attachment.this["demo_lambda_logging"] will be created
  # module.lambda_rust.aws_lambda_function.this will be created
  # module.lambda_rust.aws_lambda_permission.allow_cloudwatch[0] will be created
  # module.lambda_rust.null_resource.rust_build will be created
Plan: 10 to add, 0 to change, 0 to destroy.

3. 一時ファイルの作成にmktempを使う

teeで出力を分岐させ、プロセス置換を利用してgrep要約を適当なtmpファイルに出力させて表示してみます。

上ではこのようにしましたが、"適当なtmpファイル"を自分で指定するのも歯がゆいのでmktempコマンドで一時ファイルを作成させてみます:

tf_result_temp=$(mktemp); terraform plan | tee >(grep -E '#|Plan:' > ${tf_result_temp}) && cat ${tf_result_temp}

mktempコマンドはデフォルトで/tmp配下にファイルを作成するので、tmpファイルがplan実行毎に作成されることは気にしていません(/tmp配下のファイルは自動削除される)。

もしファイルが続々と作成されることが気に食わない場合は、最後にtmpファイルの削除を入れ込んでも良いかもしれません:

tf_result_temp=$(mktemp); terraform plan | tee >(grep -E '#|Plan:' > ${tf_result_temp}) && cat ${tf_result_temp} && rm ${tf_result_temp}


この方法での出力は、上記の "2. 元々の出力も表示する" と同じです。

おまけ: aliasを作成する

上に挙げたコマンドはどれも長くて手打ちは面倒なので、aliasを作成すると便利です。

私はこんな感じでterraformコマンドのaliasを運用しています。

alias tt='terraform'
alias ttp='terraform plan'
alias ttpp='tf_result_temp=$(mktemp); terraform plan | tee >(grep -E "#|Plan:" > ${tf_result_temp}) && cat ${tf_result_temp}'
alias tta='terraform apply'
alias ttm='terraform fmt -recursive'

dotfiles/.bash_aliases at main · bioerrorlog/dotfiles · GitHub

おわりに

terraform plan結果を要約して表示するワンライナーを組みました。

もっと良いのを思いついたらまた更新しようと思います。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

concise mode for `terraform plan` · Issue #10507 · hashicorp/terraform · GitHub

Man page of MKTEMP

GitHub - bioerrorlog/terraform-examples: My terraform example projects.

Raspberry Piで複数のサーボモーターを制御する

PWM/サーボ制御モジュールを使わずに、複数のサーボモーターを制御する方法の備忘録です。

はじめに

最近またRaspberry Piを触って遊んでいます。

複数のサーボモーターを制御したい、となったとき、世の事例を検索してみると、多くの場合はPWM/サーボ制御モジュールを取り付けることが多そうです。 ただ今回は外部モジュールを使わずに、とりあえず素のGPIOで複数サーボを制御してみました (パーツの用意やはんだ付けが面倒だったので...)。

やり方の備忘録を残します。


[関連記事] www.bioerrorlog.work

Raspberry Piで複数のサーボモータを制御する

OS環境の準備

モデルはRaspberry Pi 4 Model B (4GB RAM)を使いました。

Raspberry PiにはUbuntu 22.04.1 LTS (64-bit)を入れています (Raspberry Pi OSなど他の環境でも特に動作に違いはないはず)。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.1 LTS
Release:    22.04
Codename:   jammy

Raspberry PiにUbuntuを入れる方法は別途記事にしているので、こちらを参照ください: www.bioerrorlog.work

回路を組む

回路は↓のように組みました。

  • サーボモーターにはSG90を使用
  • サーボモーターに供給する外部電源は単4電池4本パック/6Vを使用
    (データシートによるとギリギリSG90の動作範囲)
  • 外部電源とサーボモーターのマイナス端子はRaspberry PiのGNDに接続
  • サーボモーターのPWM制御線とRaspberry PiのGPIOを1kΩ抵抗を挟んで接続
    (今回は17, 18, 27のpinを使用)

サーボモータを動かすスクリプトの用意

では、サーボモーターの動作チェックのための簡単なスクリプトを書きます。 今回はPythonで書きました。

ソースコード: github.com

import math
import time
from gpiozero import AngularServo


def main():
    servo_17 = AngularServo(17)
    servo_18 = AngularServo(18)
    servo_27 = AngularServo(27)

    t = 0
    max_angle = 60
    gap_angle = 30

    try:
        while True:
            servo_17.angle = math.sin(math.radians(t % 360)) * max_angle
            servo_18.angle = math.sin(math.radians((t % 360) + gap_angle)) * max_angle
            servo_27.angle = math.sin(math.radians((t % 360) + (gap_angle * 2))) * max_angle

            t += 2
            time.sleep(0.01)
    except KeyboardInterrupt:
        servo_17.angle = 0
        servo_18.angle = 0
        servo_27.angle = 0


if __name__ == '__main__':
    main()

gpiozeroAngularServoを使って3つのサーボを動かす、動作確認用のちょっとしたスクリプトです。 回転を滑らかにするため、角度の計算にはsin関数を挟んでいます。

サーボモータを動かす

では用意したスクリプトをRaspberry Piで実行します。

スクリプトをcloneして、必要なライブラリをRaspberry Piにインストールします:

# Clone
git clone https://github.com/bioerrorlog/raspberry-pi-examples.git
cd raspberry-pi-examples/multi_servo_gpio/

# Install required packages
sudo apt update
sudo apt upgrade
sudo apt install python3-pip python3-dev gcc git
sudo pip install -r requirements.txt

そしたら、Pythonスクリプトを実行します:

sudo python3 main.py

# sudoで実行するのは、下記エラー回避のため:
# RuntimeError: No access to /dev/mem. Try running as root!

上手く実行できれば、↓みたいな感じでサーボモーターが動きます。

(サーボモーター同士をダンボールで固定しています)

おわりに

Raspberry Piで複数のサーボモーターを制御する方法の備忘録でした。

PWM制御モジュールも使ってないし、ソフト面での工夫もしていないので結構ジッターが入ってしまいますが、とりあえず動く、というところは見ることができます。

以上、備忘録でした。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

O'Reilly Japan - Raspberry Piクックブック 第3版

マイクロサーボ9g SG-90 | 秋月電子通商

GitHub - gpiozero/gpiozero: A simple interface to GPIO devices with Raspberry Pi

GitHub - bioerrorlog/raspberry-pi-examples: Example projects for Raspberry Pi.

Raspberry PiにUbuntuをインストールする | Raspberry Pi Imager

Raspberry PiにUbuntu 22.04.1 LTSをインストールする方法の備忘録です。

はじめに

こんにちは、@bioerrorlogです。

これまではRaspberry Pi OSをインストールしていましたが、いろんなツールでの互換性を考えるとやはりUbuntuをインストールしたくなってきます。

今回はRaspberry Pi Imagerを使って、Ubuntu Desktop 22.04.1 LTS をRaspberry Piにインストールしてみます。

※環境
Raspberry Pi 4 Model B 4GB RAM

※Raspberry Pi Imagerのインストール方法は↓の記事を参照ください。 www.bioerrorlog.work

Raspberry PiにUbuntuをインストールする

以下の手順で、Raspberry PiにUbuntuをインストールしていきます。

  1. microSDをPCに挿してRaspberry Pi Imagerを起動する

    起動画面

  2. "OSを選ぶ"を選択

  3. "Other general-purpose OS"を選択

  4. "Ubuntu"を選択

  5. インストールしたいUbuntuのversionを選択
    (今回は"Ubuntu Desktop 22.04.1 LTS"を選びます)

  6. OSが選択できたので、次はストレージを選択します。
    "ストレージを選ぶ"を選択

  7. 挿入してるSDカードを選択

  8. "書き込む"を選択

  9. "はい"を選択

書き込み処理が終了したら、SDカードをPCから取り出します。

Raspberry Piを起動する

Raspberry Piの起動方法は、Raspberry Pi OSのときと変わりません。

やり方は下記リンクを参照ください。

www.bioerrorlog.work

おわりに

以上、Raspberry PiにUbuntuをインストールする方法の備忘録でした。

Raspberry Pi Imagerに従ってポチポチするだけだったので簡単ですね (この備忘録を書く必要もなかったかも)。

どなたかの参考になれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

Install Ubuntu on a Raspberry Pi | Ubuntu

ROS 2 on Raspberry Pi — ROS 2 Documentation: Foxy documentation

Raspberry Pi OSを削除する | Raspberry Pi Imager

microSD上のRaspberry Pi OSを削除する方法の備忘録です。

はじめに

こんにちは、@bioerrorlogです。

Raspberry Piで使うOSのバージョンを変えり、他のOSを入れたくなったときは、先にmicroSDに入れているOSを削除する必要があります。

今回は、microSD上のRaspberry Pi OSをRaspberry Pi Imagerで削除する方法をまとめます。

※Raspberry Pi Imagerのインストール方法は↓の記事を参照ください。 www.bioerrorlog.work

Raspberry Pi OSをmicroSDから削除する

以下の手順で、Raspberry Pi OSをmicroSDから削除します。

  1. microSDをPCに挿してRaspberry Pi Imagerを起動する
    起動画面


2. "OSを選ぶ"を選択


3. "削除"を選択


4. "ストレージを選ぶ"を選択


5. 挿入してるSDカードを選択


6. "書き込む"を選択


7. "はい"を選択


削除処理が終了したら、SDカードをPCから取り出して完了です。

削除完了画面

おわりに

以上、microSD上のRaspberry Pi OSを削除する方法のちょっとした備忘録でした。

Raspberry Pi Imagerを使えば、いろいろと面倒を見てくれるので簡単ですね。

どなたかの参考になれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

Raspberry Pi OS – Raspberry Pi

Raspberry Pi

echo $PATH結果を見やすく整形表示する

PATHを見やすく整形表示する方法のちょっとした備忘録です。

はじめに

こんにちは、@bioerrorlogです。

echo $PATHすると、そのままでは結果が見にくい状態で表示されます。

$ echo $PATH
/home/bioerrorlog/.nvm/versions/node/v16.15.0/bin:/home/bioerrorlog/.cargo/bin:/home/bioerrorlog/.local/bin:/home/bioerrorlog/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/go/bin

これを見やすく整形表示します。

※作業環境

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.5 LTS
Release:    20.04
Codename:   focal

echo $PATH結果を見やすく整形表示する

echo $PATH | tr ':' '\n'

で、:区切りではなく一覧表示にできます。

単純にtrコマンドで:を改行に変換しただけですね。

実行例

$ echo $PATH | tr ':' '\n'
/home/bioerrorlog/.nvm/versions/node/v16.15.0/bin
/home/bioerrorlog/.cargo/bin
/home/bioerrorlog/.local/bin
/home/bioerrorlog/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
/usr/local/go/bin

だいぶ見やすくなりました。

aliasを設定する

毎回このコマンドを打つのも面倒なので、aliasを設定してしまうのも手です。

alias mypath='echo $PATH | tr ":" "\n"'

実行例

$ mypath
/home/bioerrorlog/.nvm/versions/node/v16.15.0/bin
/home/bioerrorlog/.cargo/bin
/home/bioerrorlog/.local/bin
/home/bioerrorlog/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
/usr/local/go/bin

おわりに

以上、PATHを見やすく整形表示する方法のちょっとしたメモでした。

誰かの時間の節約につながれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

shell - Show PATH in a human-readable way - Unix & Linux Stack Exchange

shellコマンドを読み解くコツ

shellコマンドを読み解く際のTipsをメモします。

はじめに

こんにちは、@bioerrorlogです。

自分の知らない複雑なコマンドに出会ったときにさっと読み解けると、生産性が上がります。 昔は私も無駄にググって時間を浪費してました。

今回は過去の自分に教えるつもりで、コマンドを読み解くときのコツ/流れをメモしておきます。

shellコマンドを読み解く

--helpオプションを使う

とりあえずざっとコマンドの内容を把握するには--helpオプションを使うのがお手軽です。

大体どのコマンドにも--helpオプションは用意されているので、初見のコマンドやよくわからないコマンドに遭遇した時はさっと--helpを見るのがおすすめです。 (仮に--helpが用意されていなくても、だいたいはそのままUSAGE/使用方法が表示されるので問題ありません)

$ git --help
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           <command> [<args>]

These are common Git commands used in various situations:

start a working area (see also: git help tutorial)
   clone             Clone a repository into a new directory
   init              Create an empty Git repository or reinitialize an existing one

work on the current change (see also: git help everyday)
   add               Add file contents to the index
   mv                Move or rename a file, a directory, or a symlink
   restore           Restore working tree files
   rm                Remove files from the working tree and from the index
   sparse-checkout   Initialize and modify the sparse-checkout

examine the history and state (see also: git help revisions)
   bisect            Use binary search to find the commit that introduced a bug
   diff              Show changes between commits, commit and working tree, etc
   grep              Print lines matching a pattern
   log               Show commit logs
   show              Show various types of objects
   status            Show the working tree status

grow, mark and tweak your common history
   branch            List, create, or delete branches
   commit            Record changes to the repository
   merge             Join two or more development histories together
   rebase            Reapply commits on top of another base tip
   reset             Reset current HEAD to the specified state
   switch            Switch branches
   tag               Create, list, delete or verify a tag object signed with GPG

collaborate (see also: git help workflows)
   fetch             Download objects and refs from another repository
   pull              Fetch from and integrate with another repository or a local branch
   push              Update remote refs along with associated objects

'git help -a' and 'git help -g' list available subcommands and some
concept guides. See 'git help <command>' or 'git help <concept>'
to read about a specific subcommand or concept.
See 'git help git' for an overview of the system.

manコマンドを使う

もう少し詳しい説明が欲しい時は、manコマンドでマニュアルページを表示するのも手です。 --helpの記述よりも詳細な説明を読むことができます。

例: man git

GIT(1)                                                                                        Git Manual                                                                                       GIT(1)

NAME
       git - the stupid content tracker

SYNOPSIS
       git [--version] [--help] [-C <path>] [-c <name>=<value>]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p|--paginate|-P|--no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           [--super-prefix=<path>]
           <command> [<args>]

DESCRIPTION
       Git is a fast, scalable, distributed revision control system with an unusually rich command set that provides both high-level operations and full access to internals.

       See gittutorial(7) to get started, then see giteveryday(7) for a useful minimum set of commands. The Git User’s Manual[1] has a more in-depth introduction.

       After you mastered the basic concepts, you can come back to this page to learn what commands Git offers. You can learn more about individual Git commands with "git help command". gitcli(7)
       manual page gives you an overview of the command-line command syntax.

       A formatted and hyperlinked copy of the latest Git documentation can be viewed at https://git.github.io/htmldocs/git.html or https://git-scm.com/docs.

OPTIONS
       --version
           Prints the Git suite version that the git program came from.

       --help
           Prints the synopsis and a list of the most commonly used commands. If the option --all or -a is given then all available commands are printed. If a Git command is named this option will
           bring up the manual page for that command.

           Other options are available to control how the manual page is displayed. See git-help(1) for more information, because git --help ...  is converted internally into git help ....

       -C <path>
           Run as if git was started in <path> instead of the current working directory. When multiple -C options are given, each subsequent non-absolute -C <path> is interpreted relative to the
           preceding -C <path>. If <path> is present but empty, e.g.  -C "", then the current working directory is left unchanged.

           This option affects options that expect path name like --git-dir and --work-tree in that their interpretations of the path names would be made relative to the working directory caused by
           the -C option. For example the following invocations are equivalent:

               git --git-dir=a.git --work-tree=b -C c status
               git --git-dir=c/a.git --work-tree=c/b status

       -c <name>=<value>
           Pass a configuration parameter to the command. The value given will override values from configuration files. The <name> is expected in the same format as listed by git config (subkeys
           separated by dots).

           Note that omitting the = in git -c foo.bar ...  is allowed and sets foo.bar to the boolean true value (just like [foo]bar would in a config file). Including the equals but with an empty
           value (like git -c foo.bar= ...) sets foo.bar to the empty string which git config --type=bool will convert to false.

       --exec-path[=<path>]
           Path to wherever your core Git programs are installed. This can also be controlled by setting the GIT_EXEC_PATH environment variable. If no path is given, git will print the current
           setting and then exit.

 Manual page git(1) line 1 (press h for help or q to quit)

manページ内を検索する

manページはかなり長いので、欲しい情報を検索するのも重要です。

文字列を検索するには、manページが表示されている状態で

スラッシュ/ + 文字列

を入力し、Enterを押すと検索を開始できます。

次の検索ヒットに移動するには n を、
前の検索ヒットに移動するには Shift + n を押下します。


manページの使い方については昔に別途記事にまとめたので、よければそちらもご参考ください。

manコマンドの基本的な使い方を理解する | Linuxコマンド - BioErrorLog Tech Blog

explainshell.comを使う

最後に、explainshell.comという便利なサイトを紹介します。

explainshell.com

このサイトでコマンドを打ち込むと、それぞれのコマンド/オプションの該当マニュアルを表示してくれます

例: git log --graph --abbrev-commit --pretty=oneline origin..mybranch

自分で調べるのが面倒なほど複雑なコマンドに出会ったら、さっさとこのサイトで調べてしまうのがおすすめです。 大幅に時間を節約できます。


ちなみにこのサイトはオープンソースになっているので、中身を読んでみるのも面白そうですね。

github.com

おわりに

以上、shellコマンドを読み解くときのコツをまとめました。

コマンドを毎回ググって調べるよりも、コマンドから提供されている説明にあたるのがおすすめです。 explainshell.comも非常に便利なので、使い倒していきましょう。

どなたかの参考になれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

explainshell.com - match command-line arguments to their help text

GitHub - idank/explainshell: match command-line arguments to their help text

Ubuntuでデフォルトブラウザを変更する

Ubuntuでデフォルトブラウザを設定する方法の備忘録です。

はじめに

Ubuntuでデフォルトブラウザ設定を変更したくなりました。

パッとやり方が分からなかったので、備忘録を残します。

# 環境
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.4 LTS
Release:    20.04
Codename:   focal

Ubuntuでデフォルトブラウザを変更する

以下の手順でデフォルトブラウザを変更できます。

1. "Activities"を開く。

"Activities" を開く

2. "Default Applications"を検索して開く。

"Default Applications" を検索

3. "Web"欄からデフォルトに設定したいブラウザを選択する。

"Web"欄からデフォルトに設定したいブラウザを選択する

これで完了です。

おわりに

Ubuntuでデフォルトブラウザを変更する方法のちょっとした備忘録でした。

どなたかの役に立てば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

参考

Change which web browser opens websites by default

Ubuntuのバージョンを確認する

Ubuntuのバージョンを確認する方法をまとめます。

はじめに

こんにちは、@bioerrorlogです。

しばしばUbuntuのバージョンを確認したいときがあります。

毎回検索し直しているので、今回は備忘録にまとめます。

Ubuntuのバージョンを確認する方法

列挙していきます。

※ 動作確認はUbutnu 20.04 (仮想マシン on Windows)で行いました。

lsb_release -a

lsb_release -a
# No LSB modules are available.
# Distributor ID:  Ubuntu
# Description: Ubuntu 20.04.4 LTS
# Release: 20.04
# Codename:    focal

lsb_releaseコマンドは、Ubuntuドキュメントにも記載されているやり方です。

-aオプションは--allのことで、lsb_releaseコマンドで表示できる全ての情報を表示します。

lsb_release --help
# Usage: lsb_release [options]

# Options:
#   -h, --help         show this help message and exit
#   -v, --version      show LSB modules this system supports
#   -i, --id           show distributor ID
#   -d, --description  show description of this distribution
#   -r, --release      show release number of this distribution
#   -c, --codename     show code name of this distribution
#   -a, --all          show all of the above information
#   -s, --short        show requested information in short format

hostnamectl

hostnamectl
#    Static hostname: my-virtual-machine
#          Icon name: computer-vm
#            Chassis: vm
#         Machine ID: 46ffb6ce662940bbbc2201xxxxxxxxxx
#            Boot ID: 691d496e2c91419291ac5bxxxxxxxxxx
#     Virtualization: vmware
#   Operating System: Ubuntu 20.04.4 LTS
#             Kernel: Linux 5.4.0-122-generic
#       Architecture: x86-64

hostnamectlコマンドでは、OS情報やアーキテクチャ情報、仮想化情報を表示することができます。

cat /etc/lsb-release

cat /etc/lsb-release
# DISTRIB_ID=Ubuntu
# DISTRIB_RELEASE=20.04
# DISTRIB_CODENAME=focal
# DISTRIB_DESCRIPTION="Ubuntu 20.04.4 LTS"

cat /etc/os-release

cat /etc/os-release
# NAME="Ubuntu"
# VERSION="20.04.4 LTS (Focal Fossa)"
# ID=ubuntu
# ID_LIKE=debian
# PRETTY_NAME="Ubuntu 20.04.4 LTS"
# VERSION_ID="20.04"
# HOME_URL="https://www.ubuntu.com/"
# SUPPORT_URL="https://help.ubuntu.com/"
# BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
# PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
# VERSION_CODENAME=focal
# UBUNTU_CODENAME=focal

cat /etc/*release

上記ふたつをまとめて、cat /etc/*releaseと表示してしまうのも手です。

cat /etc/*release
# DISTRIB_ID=Ubuntu
# DISTRIB_RELEASE=20.04
# DISTRIB_CODENAME=focal
# DISTRIB_DESCRIPTION="Ubuntu 20.04.4 LTS"
# NAME="Ubuntu"
# VERSION="20.04.4 LTS (Focal Fossa)"
# ID=ubuntu
# ID_LIKE=debian
# PRETTY_NAME="Ubuntu 20.04.4 LTS"
# VERSION_ID="20.04"
# HOME_URL="https://www.ubuntu.com/"
# SUPPORT_URL="https://help.ubuntu.com/"
# BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
# PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
# VERSION_CODENAME=focal
# UBUNTU_CODENAME=focal


ちなみに/etc/*releaseにかかるのは先述の二つのファイルです。

ls /etc/*release
# /etc/lsb-release  /etc/os-release

cat /etc/issue

cat /etc/issue
# Ubuntu 20.04.4 LTS \n \l

cat /etc/issue.net

cat /etc/issue.net
# Ubuntu 20.04.4 LTS

cat /etc/issueよりもこちらの方が綺麗に表示されます。

uname -a

uname -a
# Linux my-virtual-machine 5.4.0-122-generic #138-Ubuntu SMP Wed Jun 22 15:00:31 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

この-aオプションも--allの意です。

表示する情報を絞るには各オプションが使えます。

uname --help
# Usage: uname [OPTION]...
# Print certain system information.  With no OPTION, same as -s.

#   -a, --all                print all information, in the following order,
#                              except omit -p and -i if unknown:
#   -s, --kernel-name        print the kernel name
#   -n, --nodename           print the network node hostname
#   -r, --kernel-release     print the kernel release
#   -v, --kernel-version     print the kernel version
#   -m, --machine            print the machine hardware name
#   -p, --processor          print the processor type (non-portable)
#   -i, --hardware-platform  print the hardware platform (non-portable)
#   -o, --operating-system   print the operating system
#       --help     display this help and exit
#       --version  output version information and exit

# GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
# Full documentation at: <https://www.gnu.org/software/coreutils/uname>
# or available locally via: info '(coreutils) uname invocation'

おわりに

Ubuntuのバージョンを確認する方法をまとめました。

このメモが誰かのお役に立てば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

CheckingYourUbuntuVersion - Community Help Wiki

command line - How do I check the version of Ubuntu I am running? - Ask Ubuntu

release management - How can I find the version of Ubuntu that is installed? - Ask Ubuntu

人工生命"Tierra"を動かす | ALife

Tom Rayの人工生命"Tierra"を実行する方法を整理します。

はじめに

こんにちは、@bioerrorlogです。

人工生命Tierraは、CPU timeをエネルギーとし、メモリ空間で繁殖する人工生命です。 1990年代にThomas S. Rayによって開発された、非常に有名なモデルですね。

前回はTierraのソースコードの在処を探しました:

人工生命Tierraのソースコードはどこにあるのか | ALife - BioErrorLog Tech Blog

今回はいよいよ、Tierraを動かしてみようと思います。

※ 本手順に従ってTierraを実行している様子を動画にしました:


実行環境

Linux環境を想定しています。
本記事での作業環境はこちら:

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.4 LTS
Release:    20.04
Codename:   focal

参考: WindowsにLinux仮想環境を構築する - BioErrorLog Tech Blog

実行手順

Tom Rayのホームページで配布されているソースコードは、そのままでは不具合が多く残っており上手く動作しません。

今回使う↓のコードには、既にLinux動作用に修正を当ててあります。

github.com

オリジナルのソースコードを見たい方は、v6.02-originalブランチをご覧ください。


Tierraの実行は、Tierraそのものの実行フロントエンド(Beagle)の実行の二段階に大別できます(※)。

それぞれ順番にやっていきましょう。


※ 厳密には、フロントエンドとしてbasicとBeagleが選べるような実装になっています。 が、Beagleでしか上手く動作しなかったのでそちらを使います。 今回使うコードは、そのままBeagleを使えるよう設定/不具合を修正済みです。

Tierraの実行

まずは下記コマンドで、Tierraそのものを実行します:

# 必要なライブラリをインストール
sudo apt install libncurses-dev libxt-dev libxaw7-dev x11-apps

# ソースコードをclone
git clone https://github.com/bioerrorlog/Tierra.git

# ビルド
cd Tierra/tierra
./configure
make clean
make

# gb (gene bank)生成
cd ./gb0
../arg c 0080.gen 0080aaa.tie
../arg x 0080.gen aaa
cp 0080.gen 0080gen.vir

# Tierraを実行
cd ..
HOSTNAME=localhost ./tierra si0

↓のようにTerminalで処理が実行され続けていれば成功です。

Tierra実行中のTerminalの様子

各コマンドを軽く説明します。

# 必要なライブラリをインストール
sudo apt install libncurses-dev libxt-dev libxaw7-dev x11-apps

# ソースコードをclone
git clone https://github.com/bioerrorlog/Tierra.git

最初のこの部分は前準備です。 Tierraの実行に必要なライブラリをインストールし、Tierraコードをcloneしてきます。


# ビルド
cd Tierra/tierra
./configure
make clean
make

# gb (gene bank)生成
cd ./gb0
../arg c 0080.gen 0080aaa.tie
../arg x 0080.gen aaa
cp 0080.gen 0080gen.vir

この部分で、Tierra実行ファイル/設定ファイルを生成しています。

gene bankというのは、soup (Tierraが活動するメモリ領域のこと)に最初に播種されるTierraのゲノム配列の設定ファイル群です。 ここでは各設定で初期値となっている0080aaaを使っています。


# Tierraを実行
cd ..
HOSTNAME=localhost ./tierra si0

このコマンドを実行すると、いよいよTierraが起動します。

環境変数HOSTNAMEを設定しているのは、このTierraバージョンがNetモード(インターネットを介してTierraを実行するモード)に対応しているためです。 今回はNetモードではなくローカルでTierraを起動したいので、localhostに設定します。

実行ファイルtierraに渡しているsi0というのは、soupの設定ファイルです。 Tierraが活動するメモリ領域: soup の法則(どのくらいの頻度でTierraが死亡するか、など)を調整するパラメータをここで渡します。

フロントエンド/Beagleの起動

Tierraが上手く起動できたら、次はフロントエンド(Beagle)を起動します。

新規Terminalを開き、下記コマンドを実行します。

# Beagle Explorerのビルド
cd ../Bglclnt/
make -f Makefile.Bgl clean
make -f Makefile.Bgl

# Beagle Explorerを起動
HOSTNAME=localhost ./bgl-GUI_X11-Linux

Beagleクライアントをビルドし、実行しています。 環境変数HOSTNAMEを指定しているのは、先述のTierra実行時と同じ理由です。

↓のようなウィンドウが表示されれば成功です。

Tierraのフロントエンドウィンドウ

Tierraを触って遊ぶ

無事Tierra/フロントエンド共に起動できたら、ぜひいろいろ触って遊んでみましょう。

Tierraといえば、各creatureのゲノム長が表示されたカラフルな画面が有名です。 これは、Window > Overviewで表示することができます。

その他、soupの統計情報を表示したり、特定creatureのゲノムを表示したりもできます。

詳しくは動画をご覧ください:

おわりに

以上、人工生命Tierraを実行する手順をまとめました。

Tierraは非常に有名な人工生命モデルですが、実際に実行してみたという情報はあまり見当たりません。

前回ソースコードを探すところから始め、今回コードを手に入れたものの不具合が多発し、修正には苦労しました。 (先人の軌跡を大いに参考にさせていただきました。)

この記事が、Tierraを実行してみたいと思った方のお役に立てば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

GitHub - bioerrorlog/Tierra: Tierra - Tom Ray's Artificial Life

Tierra home page

Documentation for the Tierra Simulator

Tierra

Tom Ray’s Tierra | AI 2020

Evolution, Ecology, and Optimization of Digital Organisms | Santa Fe Institute

I have always been fascinated with alife, the first one I created was something ... | Hacker News

Tierra (computer simulation) - Wikipedia

Apply tierra2011.patch · Mortal/tierra@92ff9f2 · GitHub

UbuntuでTerminalタブを開く/閉じる/移動するショートカット

UbuntuのTerminalタブ操作(開く/閉じる/移動する)ショートカットキーをまとめます。

はじめに

こんにちは、@bioerrorlogです。

普段開発にはUbuntuを使っているのですが、これまでterminalの操作には素朴にマウスを使ってました。 ショートカットを使ってスマートに作業したいなーと思い立ったのですが、意外とやりたいことが直接ヒットする日本語記事が見つかりません。

そこで今回は、terminalタブを開く/閉じる/移動するショートカットをまとめます。

作業環境

Ubuntu 20.04 LTS で作業しています。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.4 LTS
Release:    20.04
Codename:   focal

ショートカット

Terminalタブを新規で開く

Ctrl + Shift + T

でterminalの新規タブを開くことができます。

f:id:BioErrorLog:20220417115539p:plain
Ctrl + Shift + T で新規タブを開く

Terminalタブを閉じる

Ctrl + D

で現在のterminalタブを閉じることができます。

f:id:BioErrorLog:20220417115815p:plain
Ctrl + Dでタブを閉じる

Terminalタブを移動する

Alt + <num>

で指定の位置にあるterminalタブに移動することができます。

例えば、Alt + 3で3番目のタブに移動します。

f:id:BioErrorLog:20220417120225p:plain
Alt + <num>でタブを移動する

おわりに

今回はUbuntu terminalタブを開く/閉じる/移動するショートカットを簡単にまとめました。

最近はvimを使い始めたこともあり、なるべくマウスを使わずにキーボードに完結して作業を進めたい欲が高まっています。

今後も、作業効率を常に追求していきたいところです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

参考

ubuntu - How to open new tab in existing terminal session and using keyboard shortcut / modifying global settings - Super User

shortcut keys - How to close a GNOME terminal tab from the keyboard? - Ask Ubuntu

unity - How to efficiently switch between several terminal windows using the keyboard? - Ask Ubuntu

dfxをバージョン指定してインストールする | Dfinity Canister SDK

dfx (Dfinity Canister SDK)をバージョン指定してインストールする方法を整理し、その実行コマンドの中身を読み解きます。

はじめに

こんにちは、@bioerrorlogです。

Dfinity Canister SDK / dfxをインストールするときはいつも、脳を空っぽにしてドキュメントにあるコマンドをコピペしていました。

内容を気にせずにコマンド実行するのも据わりが悪いので、一度くらいはインストールコマンドを読み解いておこうと思いました。

dfxバージョンを指定してインストールするコマンドをメモし、その実行内容を整理していきます。

dfxをバージョン指定してインストールする

インストールコマンド

ドキュメントの通り、例えばバージョン0.8.2をインストールするときは次のコマンドを実行します。

DFX_VERSION=0.8.2 sh -ci "$(curl -fsSL https://sdk.dfinity.org/install.sh)"

環境変数DFX_VERSIONに任意のバージョンを指定することで、指定のdfxバージョンをインストールすることができます。

インストールコマンド読み解き

では、上記インストールコマンドの処理内容を読み解いていきます。

DFX_VERSION=0.8.2 <実行コマンド>

このようにコマンドを実行することで、環境変数DFX_VERSIONにバージョン番号を代入した状態で以降のコマンドが実行されます。 exportコマンドに環境変数宣言部分を切り出したとしても、インストールするバージョンが指定できる点は同じです。

export DFX_VERSION=0.8.0
sh -ci "$(curl -fsSL https://sdk.dfinity.org/install.sh)"


sh -ci "$(xxxxx)"

この部分ではshコマンドによって"$(xxxxx)"から受け渡される文字列がshellプロセスとして実行されます。

-cオプションによって(標準入力でなく)後続の文字列をshellで実行することを指定できます。

-iオプションはコマンドをインタラクティブに実行することを指定するオプションです。 が、現状のインストールコマンドでは特にターミナルとやり取りする要素はないので不要なのでは...?と思っています。 (実際、-i部分を抜いてコマンドを実行しても変わりなくインストールできます。)

"$(xxxxx)"では、その内部を評価した後の文字列が渡されます。 (shellにおいては、ダブルクォーテーション部分はその評価後の状態が、シングルクォーテーションでは内部がそのままの文字列として渡されます。)


curl -fsSL https://sdk.dfinity.org/install.sh

この部分でcurlコマンドによってdfxのインストールスクリプトをダウンロードしています。

-fオプションは、リクエストが失敗したときにはなにも出力させず、代わりにexitコード22を返却するようにするものです。 (リクエストが失敗したときにエラー通知用HTMLがサーバーから返されたとしても、何も出力しない挙動にすることが出来ます)

-sSによって進捗メーター表示をなくします。 (厳密には-sによって進捗メーターとエラーメッセージの表示をなくし、加えて-Sを指定することでエラーメッセージは表示するよう設定されます。)

-Lは、リクエストページが移動してた場合に新しい場所に対して再リクエストを投げるようにするオプションです。

※各オプションの詳しい説明はmanページや下記リンクが参考になります:
explainshell.com - curl -fsSL https://sdk.dfinity.org/install.sh


上記curlコマンドによってhttps://sdk.dfinity.org/install.shから取得され、shコマンドによって実行されるdfxのインストールスクリプトの中身は以下です。

長いスクリプトなので内容は網羅しませんが、次の部分でインストール先ディレクトリにdfx実行ファイルを配置し、dfxがインストールされています。

$MV "$_dfx_file" "${_install_dir}" 2>/dev/null \

スクリプト全文:

#!/usr/bin/env sh
## 000_header.sh
##
## Borrowed from rustup (https://sh.rustup.rs)
##
## This is just a little script that can be downloaded from the internet to
## install dfx. It just does platform detection, downloads the installer
## and runs it.
##
## You are NOT AUTHORIZED to remove any license agreements or prompts from the following script.
##
set -u
## install/010_manifest.sh
get_tag_from_manifest_json() {
    cat \
        | tr -d '\n' \
        | grep -o "\"$1\":[[:space:]]*\"[a-zA-Z0-9.]*" \
        | grep -o "[0-9.]*$"
}
## 020_flags.sh
DFX_BOOL_FLAGS=""
define_flag_BOOL() {
    local VARNAME
    VARNAME="flag_$(echo "$1" | tr /a-z/ /A-Z)"
    eval "$VARNAME=\${$VARNAME:-}"
    DFX_BOOL_FLAGS="${DFX_BOOL_FLAGS}--${1} $VARNAME $2"
}
get_flag_name() {
    echo "$1"
}
get_var_name() {
    echo "$2"
}
read_flags() {
    while [ -n "$*" ]; do
        local ARG=$1
        shift
        OLD_IFS="$IFS"
        IFS=$'\n'
        for line in ${DFX_BOOL_FLAGS}; do
            [ "$line" ] || break
            IFS="$OLD_IFS"
            FLAG="$(get_flag_name "$line")"
            VARNAME="$(get_var_name "$line")"
            if [ "$ARG" == "$FLAG" ]; then
                eval "$VARNAME=1"
            fi
        done
    done
}
## 100_log.sh
log() {
    if "$_ansi_escapes_are_valid"; then
        printf "\33[1minfo:\33[0m %s\n" "$1" 1>&2
    else
        printf '%s\n' "$1" 1>&2
    fi
}
say() {
    printf 'dfinity-sdk: %s\n' "$1"
}
warn() {
    if $_ansi_escapes_are_valid; then
        printf "\33[1mwarn:\33[0m %s\n" "$1" 1>&2
    else
        printf '%s\n' "$1" 1>&2
    fi
}
err() {
    say "$1" >&2
    exit 1
}
## 110_assert.sh
need_cmd() {
    if ! check_cmd "$1"; then
        err "need '$1' (command not found)"
    fi
}
check_cmd() {
    command -v "$1" >/dev/null 2>&1
}
assert_nz() {
    if [ -z "$1" ]; then err "assert_nz $2"; fi
}
ensure() {
    if ! "$@"; then err "command failed: $*"; fi
}
ignore() {
    "$@"
}
## 200_downloader.sh
define_flag_BOOL "insecure" "Allows downloading from insecure URLs, either using HTTP or TLS 1.2 or less."
check_help_for() {
    local _cmd
    local _arg
    local _ok
    _cmd="$1"
    _ok="y"
    shift
    if check_cmd sw_vers; then
        case "$(sw_vers -productVersion)" in
            10.13*) ;;
            10.14*) ;;
            10.15*) ;;
            11.*) ;;
            *)
                warn "Detected OS X platform older than 10.13 (High Sierra)"
                _ok="n"
                ;;
        esac
    fi
    for _arg in "$@"; do
        if ! "$_cmd" --help | grep -q -- "$_arg"; then
            _ok="n"
        fi
    done
    test "$_ok" = "y"
}
check_support_for() {
    local err="$1"
    shift
    local cmd="$*"
    ! ($cmd 2>&1 | grep "$err" >/dev/null)
}
downloader() {
    local _dld
    if check_cmd curl; then
        _dld=curl
    elif check_cmd wget; then
        _dld=wget
    else
        _dld='curl or wget'
    fi
    if [ "$1" = --check ]; then
        need_cmd "$_dld"
    elif [ "$_dld" = curl ]; then
        if check_help_for curl --proto --tlsv1.2; then
            curl --proto '=https' --tlsv1.2 --silent --show-error --fail --location "$1" --output "$2"
        elif ! [ "$flag_INSECURE" ]; then
            warn "Not forcing TLS v1.2, this is potentially less secure"
            curl --silent --show-error --fail --location "$1" --output "$2"
        else
            err "TLS 1.2 is not supported on this platform. To force using it, use the --insecure flag."
        fi
    elif [ "$_dld" = wget ]; then
        if check_help_for wget --https-only --secure-protocol; then
            wget --https-only --secure-protocol=TLSv1_2 "$1" -O "$2"
        elif ! [ "$flag_INSECURE" ]; then
            warn "Not forcing TLS v1.2, this is potentially less secure"
            wget "$1" -O "$2"
        else
            err "TLS 1.2 is not supported on this platform. To force using it, use the --insecure flag."
        fi
    else
        err "Unknown downloader"
    fi
}
## 999_footer.sh
SDK_WEBSITE="https://sdk.dfinity.org"
DFX_RELEASE_ROOT="${DFX_RELEASE_ROOT:-$SDK_WEBSITE/downloads/dfx}"
DFX_MANIFEST_JSON_URL="${DFX_MANIFEST_JSON_URL:-$SDK_WEBSITE/manifest.json}"
DFX_VERSION="${DFX_VERSION:-}"
SCRIPT_COMMIT_DESC="aff944417cccf34abe58dac9283fdf2b92d10458"
get_tag_from_manifest_json() {
    cat \
        | tr -d '\n' \
        | grep -o "\"$1\":[[:space:]]*\"[a-zA-Z0-9.]*" \
        | grep -o "[0-9.]*$"
}
get_manifest_version() {
    local _version
    _version="$(downloader "${DFX_MANIFEST_JSON_URL}" - | get_tag_from_manifest_json latest)" || return 2
    printf %s "${_version}"
}
validate_install_dir() {
    local dir="${1%/}"
    if ! [ -d "$dir" ]; then
        if ! mkdir -p "$dir"; then
            if type sudo >/dev/null; then
                sudo mkdir -p "$dir"
            fi
        fi
    fi
    ! [ -d "$dir" ] && return 1
    ! [ -w "$dir" ] && return 2
    case ":$PATH:" in
        *:$dir:*) ;;
        *) return 3 ;;
    esac
    return 0
}
sdk_install_dir() {
    if [ "${DFX_INSTALL_ROOT:-}" ]; then
        validate_install_dir "${DFX_INSTALL_ROOT}"
        printf %s "${DFX_INSTALL_ROOT}"
    elif validate_install_dir /usr/local/bin; then
        printf %s /usr/local/bin
    elif [ "$(uname -s)" = Darwin ]; then
        validate_install_dir /usr/local/bin
        printf %s /usr/local/bin
    elif validate_install_dir /usr/bin; then
        printf %s /usr/bin
    else
        printf %s "${HOME}/bin"
    fi
}
main() {
    _ansi_escapes_are_valid=false
    if [ -t 2 ]; then
        if [ "${TERM+set}" = 'set' ]; then
            case "$TERM" in
                xterm* | rxvt* | urxvt* | linux* | vt*)
                    _ansi_escapes_are_valid=true
                    ;;
            esac
        fi
    fi
    read_flags "$@"
    log "Executing dfx install script, commit: $SCRIPT_COMMIT_DESC"
    downloader --check
    need_cmd uname
    need_cmd mktemp
    need_cmd chmod
    need_cmd mkdir
    need_cmd rm
    need_cmd tar
    need_cmd gzip
    need_cmd touch
    get_architecture || return 1
    local _arch="$RETVAL"
    assert_nz "$_arch" "arch"
    if [ -z "${DFX_VERSION}" ]; then
        DFX_VERSION=$(get_manifest_version)
    fi
    log "Version found: $DFX_VERSION"
    local _dfx_url="${DFX_RELEASE_ROOT}/${DFX_VERSION}/${_arch}/dfx-${DFX_VERSION}.tar.gz"
    local _dir
    _dir="$(mktemp -d 2>/dev/null || ensure mktemp -d -t dfinity-sdk)"
    local _dfx_archive="${_dir}/dfx.tar.gz"
    local _dfx_file="${_dir}/dfx"
    log "Creating uninstall script in ~/.cache/dfinity"
    mkdir -p "${HOME}/.cache/dfinity/"
    install_uninstall_script
    log "Checking for latest release..."
    ensure mkdir -p "$_dir"
    ensure downloader "$_dfx_url" "$_dfx_archive"
    tar -xf "$_dfx_archive" -O >"$_dfx_file"
    ensure chmod u+x "$_dfx_file"
    local _install_dir
    _install_dir="$(sdk_install_dir)"
    printf "%s\n" "Will install in: ${_install_dir}"
    mkdir -p "${_install_dir}" || true
    if [ -w "${_install_dir}" ]; then
        MV="mv"
    else
        if ! type sudo >/dev/null; then
            err "Install directory '${_install_dir}' not writable and sudo command not found"
        fi
        MV="sudo mv"
    fi
    $MV "$_dfx_file" "${_install_dir}" 2>/dev/null \
        || err "Failed to install the DFINITY Development Kit: please check your permissions and try again."
    log "Installed $_install_dir/dfx"
    ignore rm -rf "$_dir"
}
get_architecture() {
    local _ostype _cputype _arch
    _ostype="$(uname -s)"
    _cputype="$(uname -m)"
    if [ "$_ostype" = Darwin ] && [ "$_cputype" = i386 ]; then
        if sysctl hw.optional.x86_64 | grep -q ': 1'; then
            _cputype=x86_64
        fi
    fi
    if [ "$_ostype" = Darwin ] && [ "$_cputype" = arm64 ]; then
        _cputype=x86_64
    fi
    case "$_ostype" in
        Linux)
            _ostype=linux
            ;;
        Darwin)
            _ostype=darwin
            ;;
        *)
            err "unrecognized OS type: $_ostype"
            ;;
    esac
    case "$_cputype" in
        x86_64 | x86-64 | x64 | amd64)
            _cputype=x86_64
            ;;
        *)
            err "unknown CPU type: $_cputype"
            ;;
    esac
    _arch="${_cputype}-${_ostype}"
    RETVAL="$_arch"
}
install_uninstall_script() {
    set +u
    local uninstall_file_path
    local uninstall_script
    uninstall_script=$(
        cat <<'EOF'
#!/usr/bin/env sh
uninstall() {
    check_rm "${DFX_INSTALL_ROOT}/dfx"
    check_rm "${HOME}/bin/dfx"
    check_rm /usr/local/bin/dfx /usr/bin/dfx
    clean_cache
}
check_rm() {
    local file
    for file in "$@"
    do
        [ -e "${file}" ] && rm "${file}"
    done
}
clean_cache() {
    if [ -z "$HOME" ]; then
        exit "HOME environment variable unset."
    fi
    rm -Rf "${HOME}/.cache/dfinity"
}
uninstall
EOF
    )
    set -u
    assert_nz "${HOME}"
    uninstall_file_path="${HOME}/.cache/dfinity/uninstall.sh"
    log "uninstall path=${uninstall_file_path}"
    rm -f "${uninstall_file_path}"
    printf "%s" "$uninstall_script" >"${uninstall_file_path}"
    ensure chmod u+x "${uninstall_file_path}"
}
main "$@" || exit $?

おわりに

以上、dfxをバージョン指定してインストールする方法をメモし、その実行コマンドの中身を読み解きました。

dfxのインストール方法は非常シンプルかつ処理時間も短いので、色々なバージョンの実験が気軽にできます。

触って遊んで、その挙動に慣れ親しんでいきたいものです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

Installing the SDK | Internet Computer Home

explainshell.com - curl -fsSL example.org

explainshell.com - sh -ci

What is the sh -c command? - Ask Ubuntu

Linux仮想マシンでYubiKeyを使う | VMware Workstation

VMware Workstationを使ったWindows上のLinux仮想マシンにYubiKeyを接続する方法を整理します。

はじめに

こんにちは、@bioerrorlogです。

VMware Workstationを使ったWindows上のLinux仮想マシン(Ubuntu)にYubikeyを接続しようとしたところ、次のエラーが出て接続できませんでした。

Yubico.com YubiKey OTP+FIDO+CCID をこの仮想マシンに接続できません。ホストは入力のためにこのデバイスを必要としています。

f:id:BioErrorLog:20211010102621p:plain

この問題を解決し、Linux仮想マシン上でYubikeyを使う方法をまとめます。

作業環境

こちらの手順に従って構築したWindows10上のUbuntu仮想マシンで作業しています。

  • Windows 10
  • VMware Workstation 15 Player
  • Ubuntu 20.04
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.3 LTS
Release:    20.04
Codename:   focal

Linux仮想マシンでYubiKeyを使う

.vmx ファイルを編集

まず、仮想マシンとVMware Workstationをシャットダウンした状態で .vmxファイルに以下の2行を追加します。 .vmxファイルは、仮想マシンイメージのインストールディレクトリに配置されています。

usb.generic.allowHID = "TRUE"
usb.generic.allowLastHID = "TRUE"


編集したら.vmxファイルを保存し、仮想マシンを起動します。

仮想マシン上でYubikeyを接続

仮想マシンが起動したら、下画像のように設定タブからYubikeyを接続します。

"Shared Yubico Yubikey..."の方ではなく、"Yubico.com Yubikey..."の方を選択することに注意してください。

  • Player(P)
  • 取り外し可能デバイス(R)
  • Yubico.com Yubikey...
  • 接続 (ホストから切断) (C)

f:id:BioErrorLog:20211010110425p:plain

その後表示されるウィンドウメッセージには、そのままOKを押していきます。 f:id:BioErrorLog:20211010111216p:plain

f:id:BioErrorLog:20211010111242p:plain

Yubikeyの接続を確認

ここまでくれば、YubikeyがLinux仮想マシン上で使えるようになっています。

接続できていることをlsusbコマンドで確認してみましょう。

$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 004: ID 1050:0407 Yubico.com Yubikey 4 OTP+U2F+CCID
Bus 002 Device 003: ID 0e0f:0002 VMware, Inc. Virtual USB Hub
Bus 002 Device 002: ID 0e0f:0003 VMware, Inc. Virtual Mouse
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

Yubico.com Yubikey...の記載があります。 これで、Yubikeyが仮想マシンに接続できました。

おわりに

今回は、Linux仮想マシンにYubiKeyを接続する方法を整理しました。

元々のモチベーションとして、DfinityのInternet Identityをローカルで動かしたい、でもYubikeyが仮想マシンで認識されない!という状況がありました。

思った以上にYubikey接続問題にハマってしまい、この備忘録を書くに至ります。

最終的な解決策はシンプルでした。

後世の参考になれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

Unable to get yubikey neo u2f working in Linux inside of VMWare Workstation - Super User

https://support.yubico.com/hc/en-us/articles/360013647640-Troubleshooting-Device-Passthrough-with-VMware-Workstation-and-VMware-Fusion