Linux

WSL2 Ubuntu に、nodenv 環境を作る簡単な手順(作業時間10分未満)

こんにちは、ウチイダです。

PCをセットアップするときにいつも調べている、nodeの環境構築。

そろそろ打ち止めにしたいので、メモリークリップに書き留めておきます。

今回の手順は、以下の環境で動作させました。

  • Windwos 11 Pro (21H2 ビルド 22000.194)
  • WSL カーネル バージョン: 5.10.60.1-microsoft-standard-WSL2
  • Windows Terminal バージョン: 1.10.2714.0
  • Ubuntu バージョン: 20.04.3 LTS (Focal Fossa)

nodenv installerを使うのがおすすめ

併せてanyenvを使う方法とか、homebrew経由でインストールする方法などが紹介されているサイトも多いですが、とにかく最短でnodeのマルチバージョン環境を整えたいのであれば、nodenv installerを利用するのが良いです。

必要に応じて、各種言語の管理ツールを入れるので良いかなーと思っています。

nodenv の公式リポジトリでも紹介されています。

https://github.com/nodenv/nodenv-installer#nodenv-installer

1. nodenv installer を実行する

使い方はとても簡単で、スクリプトをダウンロードしてきて、実行するだけです。

nodenv installerのgithubのREADMEでは、curlを使ったサンプルコマンドが紹介されているので、それの通りに実行します。

$ curl -fsSL https://raw.githubusercontent.com/nodenv/nodenv-installer/master/bin/nodenv-installer | bash
Installing nodenv with git...
Initialized empty Git repository in /home/y-uchiida/.nodenv/.git/

# ...(中略)...

Running doctor script to verify installation...
Checking for `nodenv' in PATH: /home/y-uchiida/.nodenv/bin/nodenv
Checking for nodenv shims in PATH: OK
Checking `nodenv install' support: /home/y-uchiida/.nodenv/plugins/node-build/bin/nodenv-install (node-build 4.9.59)
Counting installed Node versions: none
  There aren't any Node versions installed under `/home/y-uchiida/.nodenv/versions'.
  You can install Node versions like so: nodenv install 2.2.4
Auditing installed plugins: OK

All done!
Note that this installer doesn't yet configure your shell startup files:
1. You'll want to ensure that `~/.nodenv/bin' is added to PATH.
2. Run `nodenv init' to see instructions how to configure nodenv for your shell.
3. Launch a new terminal window to verify that the configuration is correct.

# nodenvがインストールできているか、バージョンを確認
$ /home/y-uchiida/.nodenv/bin/nodenv -v
nodenv 1.4.0+3.631d0b6

「All done」の表示が出たら、nodenvのインストールは完了です。

2. nodenvのインストールディレクトリにパスを通す

nodenv installerは、パスの追加までは行わないので、パスの追加を行います。

Ubuntuの初期設定であれば、ログインシェルはbashになっていると思いますので、ホームディレクトリの.bashrcの末尾に、以下を追記します。

# nodenv のインストールディレクトリをPATHに追記
export PATH="$HOME/.nodenv/bin:$PATH"

# nodenvを動作させるための設定を実行
eval "$(nodenv init -)"

追記が終わったら、bashを立ち上げなおすか、sourceコマンドで変更を反映します。

$ source ~/.bashrc

# コマンド名だけでバージョン確認できたら、パスの追加は完了
$ node -v
nodenv 1.4.0+3.631d0b6

3. node のインストール

nodenvがインストールできたので、nodeをインストールします。

とりあえずLTSの最新版を入れてみます。

LTSのバージョン情報は、下記のNode.js公式サイトのトップに書いてあるので、それを見るのが早いです。

https://nodejs.org/ja/

2,021年10月現在だと、ちょうどv14系からv16系に安定板が切り替わるタイミングです。

https://nodejs.org/ja/about/releases/

10月26日からがv16のLTSのスタートなので、ちょっと早いですが(執筆時点では10月14日です)、v16を入れておくことにします。

# nodenvで、最新版をインストール(公式サイトでバージョン番号を確認してください)
$ nodenv install 16.11.1
Downloading node-v16.11.1-linux-x64.tar.gz...
-> https://nodejs.org/dist/v16.11.1/node-v16.11.1-linux-x64.tar.gz
Installing node-v16.11.1-linux-x64...
Installed node-v16.11.1-linux-x64 to /home/y-uchiida/.nodenv/versions/16.11.1

# インストールしたバージョンを、システム全体で利用するように設定
$ nodenv global 16.11.1

# 設定できたか、バージョンを確認
$ node -v
v16.11.1

nodeがインストールできていれば、npmも入っています。

ちょっとした開発や検証なら、ここまでの設定で不自由することはないと思います。

バージョンを分けて管理したい場合は、nodenv local コマンドで、動作させるバージョンを切り替えてください。

もっと本格的に使うのであれば、Dockerなどを使って環境を分離することをお勧めします。

アンインストール

ホームディレクトリ内に追加されている「.nodenv」ディレクトリに関連データが入っていますので、それを削除すればOKです。

# nodenv のアンインストール、削除
$ rm -r ~/.nodenv

.nodenvディレクトリを削除すると、今までインストールしたnodeのバージョンとか設定とか全部まとめて消えてしまいます。

必要に応じてバックアップをしてください!

まとめと余談

以上でnodejs/nodenvの環境構築は完了です。

検索結果の上位に出てくる方法は、brewをインストールしたり、anyenvの中のnodenvを使うような網羅的な方法が出てくることが多いように思います。

ちょっとnodeのバージョン管理がしたいだけなのに手間が多いな~と思っていたので、シンプルな方法をまとめました。

ここからバリバリ開発していきましょう!

ちなみに、ウチイダは過去にanyenvをWSL Ubuntuで利用していて、起動がとても遅くなった経験をしたことがあります。

最近では、本格的に開発をする場合Dockerに環境を用意することが多いのではないでしょうか。

そのため、anyenvでまとめて管理しないといけないほど、WSL上で直接いろいろな言語の開発環境が必要になることは少ないと思っています。

起動時間のことなどもかんがみて、ホスト側(厳密には、WSLはホストじゃないですが…)の環境はシンプルに保っておきたいです。

以上です。あなたのお役に立てればうれしいです。

vsftpd が動かない→ 設定ファイルの改行コードをLFに変える

みなさまこんにちは、ウチイダです。

先日、Dockerでの環境構築をする中でvsftpdを使ったFTPサーバを用意していた時のこと。

デーモンが起動しないというトラブルに遭遇しました。

# vstftpd /etc/vsftpd.conf
500 OOPS: bad bool value in config file for: listen

DockerのCOPYコマンド経由で、ホストからvsftpd.confを渡していたのですが、どうもその内容にエラーがあるとのこと。

散々見比べても問題なさそうだったのですが、デフォルトの内容とdiffを取ってみたら、すべての行で差分が出ていました。

これは…改行コードか!!

ホスト側から渡していたファイルの改行コードがCRLFになっていたので、これをLFに保存しなおして再度チャレンジ。

何事もなかったかのように動きました。

スペースが入っているだけでもディレクティブ名と値の間にスペースが入っていてもNGだったり、vsftpdのコンフィグの設定に気を使いますね…

これに限らないのかもしれませんが、Windows ホストの場合は改行コードが違うということは改めて意識しておこうと思いました…

以上です。

あなたのお役に立てればうれしいです。

tar コマンドでカレントディレクトリ以外のディレクトリを指定してアーカイブしたい

こんにちは、ウチイダです。

tar コマンドでアーカイブをするとき、わざわざ対象のディレクトリまで移動するのが面倒な時ってあるじゃないですか。

例えば、Dockerfileでのビルドの際に何かを圧縮するときとか。

あるいは、make コマンドで処理を自動化している場面とか。

そんな時に、横着してディレクトリ移動せずにtar でのアーカイブを実行してしまうと、解凍したときのディレクトリ構造が面倒なことになってしまいます。

# piyo を起点にしてアーカイブしたいのに、カレントディレクトリの直下のディレクトリが含まれてしまう
$ tar zcfv archive.tar.gz ./tar_test/hoge/fuga/piyo
./tar_test/hoge/fuga/piyo/
./tar_test/hoge/fuga/piyo/hogefuga/
./tar_test/hoge/fuga/piyo/hogefuga/fugapiyo/
./tar_test/hoge/fuga/piyo/hogefuga/fugapiyo/text.txt

ディレクトリを指定しても、そのディレクトリに到達するところまで、アーカイブに含まれてしまうんですよね。

これを展開すると、tar_test を起点としてデータが展開されます。

cd で移動したくないときは、-C を使うとよいようです。

$ tar zcfv archive.tar.gz -C ./tar_test/hoge/fuga/ piyo
piyo/
piyo/hogefuga/
piyo/hogefuga/fugapiyo/
piyo/hogefuga/fugapiyo/text.txt

今度は、tar_test やその下のhogeなどが含まれず、piyoを起点としてアーカイブを作ることができました。

カレントディレクトリを変えずに、アーカイブファイルの起点を変更したいときはお試しください。

以上、あなたのお役に立てればうれしいです。

WSL上のDocker Composeで作成したコンテナに、Windows 11ホストから接続する

こんにちは、ウチイダです。

ここしばらく、Windwos 11のWSL Ubuntu での環境構築を進めてきました。

前回の記事で、Docker Composeのインストールを紹介しています。

今回はその続きとして、シンプルなPHP開発環境をDocker Compose を用いて作成し、Windows ホストのブラウザからアクセスできるように設定していきます。

これができると、ついにWindows 11でWSLを使った実用的なWeb開発ができるようになります。

なお、動作環境は以下の通りです。

  • Windwos 11 Pro (21H2 ビルド 22000.120)
  • WSL カーネル バージョン: 5.10.16
  • Windows Terminal バージョン: 1.9.1942.0
  • Docker バージョン 20.10.8, build 3967b7d
  • Docker Compose バージョン 1.29.2, build 5becea4c

前準備①:Docker デーモンを起動する

WSLのディストリビューションは、サービスの自動起動などを行いません。

WSLを起動した後、最初にDockerを利用する場合は、デーモンを起動するのを忘れないようにしましょう。

$ sudo service docker start
[sudo] password for y-uchiida:
 * Starting Docker: docker                                 [ OK ]

## Docker デーモンの起動を確認します
$ service docker status
 * Docker is running

前準備②:開発環境をつくるディレクトリを作成

続いて、Docker に関するファイルや、PHPなどのスクリプトを置くディレクトリを作成します。

例として、「sample_docker-compose_on_wsl」を作成します。

また、PHPやJavaScriptなどのデータを置くための「public」も作成しておきます。

## とりあえずホームディレクトリに作ることにします
## 開発環境をまとめておく場所を決めている方は、そちらに作成してください
$ mkdir ~/sample_docker-compose_on_wsl

## 公開用ファイルを設置するpublic ディレクトリを作成します
$ mkdir ~/sample_docker-compose_on_wsl/public 

前準備③:ファイル編集とDocker実行の準備

この後の作業で、yamlファイルを編集したりdocker-compose コマンドを実行したりするので、作成した開発環境用のディレクトリに移動しておきます。

また、エディタも用意します。以下の例では、VS Codeでsample_docker-compose_on_wsl ディレクトリを開いています。

## docker-compose コマンドを使うので、カレントディレクトリを移動しておきます
$ cd ~/sample_docker-compose_on_wsl

## Visual Studio Code(VS Code) を利用している方は、code コマンドでVS Codeで開くことができます
## docker-compose.ymlの編集などはVS Code
$ code .

docker-compose.ymlを作成する

準備が整いましたので、Docker Compose でコンテナを生成・起動するためのファイル docker-compose.ymlを作っていきます。

sample_docker-compose_on_wsl ディレクトリ配下に作成します。

完成コードは以下です。

ディスク容量を圧迫しないように、alpine ベースのイメージを選択しました。

version: '3.8' # 現時点での最新のバージョンを指定しておきます
services: 

  # Webサーバとして、nginx を利用します
  web: 
    container_name: "web"
    image: nginx:1.21.1-alpine
    ports:
      - "8080:80" # ポート8080を、ポート80 へフォワーディングします
    links:
      - app # php 実行コンテナ(app)に接続できるようにします
    volumes:
      - ./public:/var/www/public # WSL側のpublic ディレクトリを、web コンテナにマウントします
      - ./default.conf:/etc/nginx/conf.d/default.conf # nginx の設定ファイルを、web コンテナにマウントします

  app:
    container_name: "app"
    image: php:7.4-fpm-alpine3.14
    volumes:
      - ./public:/var/www/public # web コンテナと同じパスにアクセスできるように、app コンテナにもpublic ディレクトリをマウントします

ここでのポイントは2点あります。

ひとつは、links でweb コンテナから app コンテナに接続できるように設定したことです。

これにより、phpファイルが呼び出された際にapp コンテナへ処理を引き渡すことができるようになります。

もうひとつは、web と app の両方の volumes に./publicをマウントするように記述したことです。

同じファイルパスで参照できるようになるので、スムーズに処理の引き渡しができます。

コンテナにマウントするファイルを作成する

続いて、コンテナにマウントするファイルを作っていきます。

最低限の用意として、2つのファイルを作成します。

phpの処理をapp コンテナに引き渡すための設定を記述したnginxのconfigファイル「default.conf」と、publicルートにアクセスした際に処理される「index.php」です。

default.confの作成

まずは、nginxの設定ファイルから見ていきます。

sample_docker-compose_on_wsl ディレクトリの直下に、以下のdefault.conf を作成してください。

server {
    listen 80;
    server_name localhost;

    root /var/www/public;
    index index.php;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    # PHP ファイルへアクセスされた場合に、app コンテナのfast CGIへ処理を回します
    location ~ \.php$ {
        include fastcgi_params;

        # app コンテナのポート9000でFast CGI がListenしているので、そちらへパスします
        fastcgi_pass app:9000;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_index index.php;

        # nginx がアクセスされたファイルパスを、app コンテナで処理すべきファイルパスとして渡します
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;

        try_files $uri = 404;
    }
}

ポイントは、 location ~ \.php のディレクティブです。

ここで、php ファイルにアクセスされた際にapp コンテナへ処理を移すための設定を記載しています。

app コンテナのポート9000でFast CGI がListenしているので、fastcgi_pass はapp:9000 を指定します。

また、SCRIPT_FILENAME で、nginx がアクセスされたファイルパス($dcoument_root$fastcgi_script_name)を渡しています。

docker-compose.yml では、2つのコンテナにpublic ディレクトリを同じパスにマウントしました。

コンテナ同士のphpファイルのパスを一致させているため、このように記述できます。

index.php の作成

最後に、index.php を作成します。

これは、phpが動作していることが分かれば何でもよいです。

public ディレクトリ内に作成します。

<?php
    echo "hello from docker on wsl!!<br>\r\n";

内容は、好きなように設定してください。

コンテナの起動と動作確認

準備が整いましたので、docker コンテナを起動して動作を見ていきます。

まずはコンテナの起動です。

## dockerコンテナの起動には、sudo が必要になると思います
## コンテナ起動後にほかのコマンドを使いたいので、最後に & をつけてバックグラウンドで処理させます
$ sudo docker-compose up &
Creating app ... done
Creating web ... done
Attaching to app, web
app    | [09-Aug-2021 09:19:39] NOTICE: fpm is running, pid 1
app    | [09-Aug-2021 09:19:39] NOTICE: ready to handle connections
web    | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
web    | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
web    | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
web    | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
web    | 10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf differs from the packaged version
web    | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
web    | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
web    | /docker-entrypoint.sh: Configuration complete; ready for start up
web    | 2021/08/09 09:19:40 [notice] 1#1: using the "epoll" event method
web    | 2021/08/09 09:19:40 [notice] 1#1: nginx/1.21.1
web    | 2021/08/09 09:19:40 [notice] 1#1: built by gcc 10.3.1 20210424 (Alpine 10.3.1_git20210424)
web    | 2021/08/09 09:19:40 [notice] 1#1: OS: Linux 5.10.16.3-microsoft-standard-WSL2
web    | 2021/08/09 09:19:40 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
web    | 2021/08/09 09:19:40 [notice] 1#1: start worker processes
web    | 2021/08/09 09:19:40 [notice] 1#1: start worker process 32
web    | 2021/08/09 09:19:40 [notice] 1#1: start worker process 33
web    | 2021/08/09 09:19:40 [notice] 1#1: start worker process 34
web    | 2021/08/09 09:19:40 [notice] 1#1: start worker process 35

コンテナ起動時のメッセージがたくさん出ます。最後にstart worker process (番号) と表示されれば成功です。

コンテナの起動コマンドの最後に 「&」 をつけておくと、コンテナの起動がバックグラウンドで処理されます。

バックグラウンド処理にしておくことで、up コマンド実行後も同じターミナルで別のコマンドが実行できます。

WSLからコンテナにアクセス

まずはDocker コンテナのホストであるWSL から、コンテナへアクセスしてみます。

8080ポートをフォワーディングしているので、localhost:8080でコンテナ内のnginxへアクセスできます。

curl コマンドを用いて、レスポンスを確認します。

$ curl http://localhost:8080/
hello from docker on wsl!!<br>
app    | 172.22.0.3 -  09/Aug/2021:10:07:27 +0000 "GET /index.php" 200
web    | 172.22.0.1 - - [09/Aug/2021:10:07:27 +0000] "GET / HTTP/1.1" 200 43 "-" "curl/7.68.0"

index.php でechoした文字列「hello from docker on wsl!!」が表示されています。

また、web コンテナ、app コンテナそれぞれがメッセージを出してきました。

このような表示になれば、うまく設定できています。

index.php の内容を変更・保存し、再度curl コマンドを実行すると、表示内容が変わります。

Windows ホストのブラウザからコンテナにアクセス

最後に、Windows上のブラウザからコンテナにアクセスしてみます。

以前はWindows ホストからWSLにアクセスするには設定が必要だったのですが、今ではとくに何もしなくてもよいようです。

ブラウザを開き、localhost:8080にアクセスしてみます。

あっさり接続できてしまいました。

WSLのDockerで、こんなに簡単にPHP開発環境が作れるとは驚きです。

Docker コンテナを終了する

一通り動作確認をしたら、Docker コンテナを終了します。

$ sudo docker-compose down
Stopping web ...
Stopping app ...
web    | 2021/08/09 10:45:04 [notice] 1#1: signal 3 (SIGQUIT) received, shutting down
web    | 2021/08/09 10:45:04 [notice] 33#33: gracefully shutting down
web    | 2021/08/09 10:45:04 [notice] 34#34: gracefully shutting down

... 中略 ...

Removing web ... done
Removing app ... done
Removing network sample_docker-compose_default
[1]+  Done                    sudo docker-compose up

またコンテナにアクセスしたい場合は、 docker-compose up を実行してください。

まとめ:WSLでも、スムーズにPHP開発環境が構築できるようになりました

今回はこれで終了です。

2021年8月時点では、とても簡単にWSLを使ったPHP開発環境が構築できるようになっていました。感動。

Docker Compose を使いたかったので長くなってしまいましたが、Windows ホストからWSL 上のDocker コンテナにつなげるだけだったら、もっと簡単にできそうです。

PHP のほかにも、node.js やPython の環境も、同じ要領で構築できそうです。

ここから先はDocker の領域に入っていきますので、Docker に関する情報などをあたってみるとよいかと思います。

以上、あなたのお役に立てれば幸いです。

CentOS 8でXEyesを利用する

Linuxのコマンド操作の練習としてよく利用されているXEyes。

この間もLinuxの研修を行ったときに受講者に試してもらったのですが、CentOS 8では初期状態ではインストールできなくなっていました。

[root@localhost /]# dnf search x11-apps
一致する項目はありませんでした。
[root@localhost /]#

XEyesを含むx11-appsが見つかりません。

調べてみたところ、どうやらpower-tools というリポジトリを有効化しないといけないようです。

[root@localhost /]# dnf config-manager --set-enable powertools
[root@localhost /]# dnf search x11-apps
CentOS Linux 8 - PowerTools                            848 kB/s | 2.3 MB     00:02    
================================= 名前 一致: x11-apps =================================
xorg-x11-apps.x86_64 : X.Org X11 applications
[root@localhost /]# 

x11-appsをインストールすると、xeyes コマンドが利用できるようになりました。

以上です。あなたのお役に立てればうれしいです。

LinuxでSIGBUSを発生させる

C言語を扱う中で、バスエラー(BUSE. SIGBUS)について調べたのでメモを残しておきます。

本記事のコードは、WSL2のUbuntuで動作させた結果を掲載しています。

一応、以下に検証した動作環境を。

環境・バージョンなど

  • Windows 10 Pro 20H2 (OSビルド: 19042.782)
  • Windows Subsystem for Linux Update 5.4.72
  • Ubuntu 20.04.2 LTS

バスエラーは物理メモリやハードウェアバスに関するエラー、、、らしい

バスエラー(BUSE)は、CPUが物理メモリにアクセスしたときに発生するエラーだとのこと。存在しないデバイスや、制限されているデバイスへのアクセスで発生する、との記載も見かけました。

むむ、難しい。確保してないメモリに触ったときはSEGVが発生するけど、そうじゃないメモリのエラーで発生するということですかね。

メモリアライメント違反とかでもおこるようです。

発生させてみる

とりあえず、実際に発生させてみましょう。思いついたものから試してみます。

スタック領域の文字列の範囲外を書き換え

ヒープ領域ではなくスタック領域のメモリの範囲外へのアクセスだとどうなるでしょうか。スタック領域が物理メモリなのかどうかわからないですが。。。

int	main(void)
{
	char str[3] = "abc";

	str[3] = 'd';
	return (0);
}
$ gcc test_buse.c -o a.out
$ ./a.out
*** stack smashing detected ***: terminated
Aborted

思ってたのと違う実行結果でした。これも物理メモリではなかったということですかね。

ていうか、スタック領域のメモリの外側に触れると、ちゃんとその旨表示するんですね。知らなかった。

アライメント不整合のメモリアクセス

次は、調べてみたときに見かけた「メモリアライメント違反」の場合を試してみます。

#include <stdio.h>
#include <stdlib.h>

int	main(void)
{
	long *l;
	char *c;

	l = (long *)malloc(sizeof(long) * 2);

	/* ポインタ変更前 */
	printf("l(%p): %ld\n", l, *l);

	/* longのポインタをcharのポインタに代入して、1バイトだけ動かしてから戻す */
	c = (char *)l;
	c++;
	l = (long *)c;

	/* 変更前から1バイトずれて、アライメント違反になっているはず */
	printf("l(%p): %ld\n", l, *l);

	return (0);
}
$ gcc test_buse2.c -o a.out
$ ./a.out
l(0x562c8fdef2a0): 0
l(0x562c8fdef2a1): 0

あれっ、エラーにならず正常終了してしまいました…明らかに不整合なのに…

もうちょっと調べてみたところ、アライメント違反のチェックフラグがデフォルトでオフになっているようです。

EFLAGSのACをオンにすると検知してくれます。

#include <stdio.h>
#include <stdlib.h>

int	main(void)
{
	/* asmでEFLAGSを変更 */
	asm( "pushf\n\torl $0x40000,(%rsp)\n\tpopf");

	long *l;
	char *c;

	l = (long *)malloc(sizeof(long) * 2);

	/* ポインタ変更前 */
	printf("l(%p): %ld\n", l, *l);

	/* longのポインタをcharのポインタに代入して、1バイトだけ動かしてから戻す */
	c = (char *)l;
	c++;
	l = (long *)c;

	/* 変更前から1バイトずれて、アライメント違反になっているはず */
	printf("l(%p): %ld\n", l, *l);

	return (0);
}
$ gcc test_buse3.c -o a.out
$ ./a.out
Bus error

めでたくバスエラーが発生しました。

アセンブリわかんないな~…近いうち勉強しないと…

バスエラー、めったに見る機会がなさそう

昔は、アライメント違反で普通に発生してたんですかね…

いまはデフォルトでチェック機能がオフになっているので、意図的に検知させないとめったに遭遇しないんじゃないでしょうか。

けっきょく、物理メモリとかハードウェアバスのところまでは理解が及びませんでしたが…

どうやら前提知識が不足しているっぽいので、いまは深追いせずにペンディングにしときます。

説明できるようになったら、また記事追加しようと思います。

以上、あなたのお役に立てれば幸いです。

Makefileでのコマンド実行は $(shell command)

Makefileでdockerのイメージやコンテナをあれこれしたいという事情があって(これです)、その際に躓いたのでメモしておきます。

指定の名称のdocker コンテナがあるかどうかで処理を分ける、ということをしたかったので、以下のような感じでMakefileにターゲットを作成しました

test_container_exist:
	if [ $(docker ps -qa -f name=${NAME}) ]; then \
		echo container $(NAME) is exist. ; \
	else \
		echo contaier $(NAME) is not exist. ; \
	fi

実際に動かしてみると、条件として設定してあるdockerコマンドの実行結果が空っぽになってしまい( if [ ]; then になっている )、コンテナの有無にかかわらず常にelseのほうが実行されてしまうのでした。

コマンドラインから上記のdocker コマンドを実行すると、ちゃんと指定の名称のコンテナIDが返ってくるのですが…

いろいろ調べていたところ、どうやらMakefileの中でコマンドを実行するには $(shell command)とする必要があるとわかりました。

test_container_exist:
	# docker コマンドの前に、"shell" と付記する
	if [ $(shell docker ps -qa -f name=${NAME}) ]; then \
		echo container $(NAME) is exist. ; \
	else \
		echo contaier $(NAME) is not exist. ; \
	fi

できましたできました。こんなことに小一時間もかけてしまった…?

RTFMな事案でした。ちゃんとドキュメントに目を通すようにしたいです。

あなたのお役に立てれば幸いです。

ポートを利用しているプロセスを調べる: lsof -i :

netstat コマンドが使えない環境のとき。

nodeのWebサーバをkillするために、pidを調べる例。

$ lsof -i :8080
COMMAND   PID       USER  FD   TYPE  DEVICE  SIZE/OFF  NODE  NAME
node    23294  y-uchiida  19u  IPv6  671963       0t0   TCP  *:8080 (LISTEN)

ちなみにlsof は、”list open file” の略です。知らなかった。

あなたのお役に立てればうれしいです。

サブドメインを別のネームサーバで管理する

実験用のドメインで、ある特定のサブドメインだけ別のネームサーバで設定を管理することになったので、その際の作業について。

サブドメインのサブドメイン、、、を設定していたらちょっと混乱したので、基本に立ち返ってネームサーバの委任方法をメモしておきます。

特定のサブドメインだけ、別のネームサーバのレコードを参照させるには、

  • 委任するネームサーバのゾーンファイルに、委任を受けるネームサーバを、委任するサブドメイン用のNSレコードに記述する
  • 委任を受けるネームサーバのゾーンファイルに、委任を受けるネームサーバをNSレコードに記載する

の2点を行う必要があります。

文章で書くと分かりづらいですね。。。

要するに、

$ORIGIN example.com.
; ... 前略
; 親ドメインのゾーンファイルには、委任するサブドメインを管理するネームサーバを記載する
sub.example.com.        IN      NS     ns-another.example2.com.
; ... 後略
$ORIGIN sub.example.com.
; ... 前略
; サブドメインのゾーンファイルにも、同じくNSレコードを記述する
sub.example.com.          IN     NS  ns-another.example2.com.
; ... 後略

こういうことでした。

ちなみに、委任先のネームサーバが委任するサブドメイン(sub.example.com)内にある場合は、親のネームサーバのAレコードに、委任先ネームサーバのIPアドレスを記述します。

これがきちんと設定できていないと、

$ nslookup sub.example.com
** server can't find sub.example.com: NXDOMAIN

こんな感じのエラーが出ます。

サブドメインを別のネームサーバに管理させる場合は、親のネームサーバにもこのネームサーバにも、NSレコードの記述が必要という話でした。

あなたのお役に立てればうれしいです。

sshでログインできないエラー:tilde_expand_filename: No such user

新しいサーバーをつくって、ローカルPCからsshでログインしようとした際に上記のエラーが出ました。

検索してみたけど、日本語の情報があまり出てこなかったのでメモしておきます。

原因は本当にしょうもなくて、configファイルの記述ミスでした。

Host ssh-host
  HostName hostname.example.com
  User username-example
  IdentityFile ~./ssh/ssh-host/private.rsa

こんな感じで記述したところ、以下のようなエラーが。

$ ssh ssh-host
tilde_expand_filename: No such user .

sshとの関係で調べてみても、それらしい情報に出会えず。

和訳すると「チルダのファイル名展開」みたいな意味です。

チルダか~…と思いながらconfigを見直してみたら、誤入力を発見しました。

Host ssh-host
  HostName hostname.example.com
  User username-example
#  IdentityFile ~./ssh/ssh-host/private.rsa # <- ~の後ろに '.'が入っている
  IdentityFile ~/.ssh/ssh-host/private.rsa # <- '~/.ssh'に修正

普通に入力ミスでした。

No such userじゃなくて、 No such file だったらすぐに気づいたんだけど…

ちなみに、チルダの後ろの誤入力を「foobar」にしたら、ちゃんと(?)

$ ssh ssh-host
tilde_expand_filename: No such user foobar

というエラーになりました。

誤入力には気を付けましょう、という話でした。

あなたのお役に立てましたらうれしいです。