y-uchiida

ポートを利用しているプロセスを調べる: 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

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

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

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

多重ポインタのインクリメントはかっこが必要

文字列のポインタのポインタ(多重ポインタ)を利用する場面で、インクリメントをしようとしたらエラーになりました。

void func(char **p)
{
  /* 1文字ずつ処理したかった */
  while (**p != '\0')
  {
    /* ここに処理 */
    *p++; // インクリメントで参照先を一つずつ移動
  }
  return ;
}

そうしたら、コンパイル時に以下のエラーが。

error: value computed is not used [-Werror=unused-value]

どうやらこの書き方だと、*(p++) と解釈されてしまうようです。

void func(char **p)
{
  /* 1文字ずつ処理したかった */
  while (**p != '\0')
  {
    /* ここに処理 */
    (*p)++; // ポインタを示すようにかっこで囲む
  }
  return;
}

このように変数部分にかっこをつける修正をしたところ、エラーが解消しました。

間接参照演算子の優先順位が、インクリメント記号よりも低いことが原因とのこと。

これ知らなかったらハマるやつですね。メモっておこう。

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

dockerコンテナ内でNginxの起動状態を確認する : ps r コマンド

dockerコンテナ内では、 systemctl や service コマンドが利用できません。

いつものクセでコンテナ化していない環境と同じコマンドを実行するとエラーします。

# / systemctl status nginx
sh: systemctl: not found

実行プロセスの有無で起動状態かそうでないかを判断する

代わりの方法として、プロセスがあるかどうかで判断をしてみます。

# / ps r | grep nginx
    1 root      0:00 nginx: master process nginx -g daemon off;
  101 nginx     0:00 nginx: worker process
  102 nginx     0:00 nginx: worker process
  103 nginx     0:00 nginx: worker process
  104 nginx     0:00 nginx: worker process
  106 root      0:00 grep nginx

rオプションで実行中のプロセスの一覧を表示し、grepでnginxのものだけを絞り込みます。

プロセスがあればNginxが起動していて、何も表示されなければNginxが起動していない…と考えることができます。

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

符号付き2進数は最上位ビットだけ1のときが最小値になる

なにを当たり前のことを…とお思いかもしれませんが、これがなかなか腑に落ちなかったのです。

だって、絶対値が大きいほうが、負の数は小さくなるじゃないですか。
(0111)2 が7なら、符号ビット入れ替えて(1111)2 にしたら、-7になりそうじゃないですか。

これが、実際のところは-1になるとか、普段の感覚からは飛躍しすぎなのです。

まあ、ようするに補数表現が理解できてなかったんですよね。

コンピュータのビット演算には桁あふれというものがある

計算可能なビット列の範囲からあふれた値が消えるということを実感できれば、簡単なことでした。

っていうか、2進数の加算、減算をいくつかプログラム書いて実際に動かしているうちに、「2つの符号付き2進数を足して0になる」とはどういうことか実感できたということなのですが。

(0100)2 は、符号付き2進数で4を表します。4に何を足したら0になるかというと、もちろん-4です。

では、-4は符号付き2進数でどう表されるでしょうか。
(0100)2 との演算結果が (0000)2 になればいい、ということです。

加算して桁あふれさせることで(0000)2 になる値が、-4を表しているということです。

ビット反転して1足して、、、(1100)2 。これが符号付き2進数での「-4」です。

bit 5bit 4bit 3bit 2bit 1
0100
+1100
=10000

4 = (0100)2 に-4 = (1100)2 を加算してみたら、桁あふれして0になりました。

これは、普通の10進数での計算の感覚である 4 + (-4) = 0と一致します。
ああすっきり。めでたしめでたし。

もう一つの考え方:0から1引いたらどうなるか

上記のほかにもう一つ発見をしました。

(0011)2 これは2進数表記の3です。ここから1引いたら(0010)2 、さらに1引いたら(0001)2 になります。ここまでは普通の感覚と同じです。

(0000)2 は0ですね。ここからさらに1ひいて、-1になるときはどうでしょうか。

これは、桁下がりと同じ考え方でよいのです。100から1引いたら、99になりますね。
桁下がりによって下の桁の数字は大きくなります。

2進数でも同じです。(0000)2 から-1引いたら、(架空の)5桁目から桁下がりしてきたと考えます。

というわけで、 0 = (0000)2 から1を引いた結果である -1は、 (1111)2 なのです。

ここからさらに1を引くと、 -2 = (1110)2 となります。

順番に1を引いていって、 (1000)2 が、4ビットの符号つき整数で表現できる最小値である -8 となります。

(0000)20
(1111)2-1
(1110)2-2
(1101)2-3
(1100)2-4
(1011)2-5
(1010)2-6
(1001)2-7
(1000)2-8

これは、ビットの桁数がいくつでも変わりません。

符号付き2進数のすべての桁が1のときは、常に-1です。

そして、最上位ビット(符号ビット)だけ1のときが、表現可能な範囲での最小値になります。

屁理屈っぽいですが、そういうことなのです。

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

C言語の左シフト演算は符号付きの場合も論理シフトする

本当は言語としては未定義なのですが、主要なコンパイラは論理シフト演算として実装しているようです。gccとclangでは論理シフトしました。

#include <stdio.h>

int main()
{
    // 1byteのsigned charで検証
    signed char signed_1;
    signed char signed_2;

    //0b接頭辞で2進数を表現できる
    signed_1 = 0b01010000; // -> 80
    signed_1 = signed_1 << 1; // -96(0b10100000)
    printf("sigined_1: %d\n", signed_1);

    signed_2 = 0b10111111; // -> -65
    signed_2 = signed_2 << 1; // 126(0b01111110)
    printf("signed_2: %d\n", signed_2);
}

算術シフトのつもりでビットシフトするとハマりますね。

ちなみに、右シフトはちゃんと算術シフトされます。

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

Basic認証のせいでcertbotがエラーになるので認証を除外した

Let’s EncryptでSSL証明書を発行しようと思ったら、401エラーが出ました。

$ sudo certbot certonly --dry-run --webroot -w /var/www/public -d www.example.com

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for www.example.com
Using the webroot path /var/www/public for all unmatched domains.
Waiting for verification...
Challenge failed for domain www.example.com
http-01 challenge for www.example.com
Cleaning up challenges
Some challenges have failed.

IMPORTANT NOTES:
 - The following errors were reported by the server:

   Domain: www.example.com
   Type:   unauthorized
   Detail: Invalid response from
   https://www.example.com/.well-known/acme-challenge/B8EC9m985Ywm9c3xxLEnrB4uU8shlEOF5s6-Fr_CHHM
   [XXX.XXX.XXX.XXX]: "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML
   2.0//EN\">\n<html><head>\n<title>401
   Unauthorized</title>\n</head><body>\n<h1>Unauthorized</"

   To fix these errors, please make sure that your domain name was
   entered correctly and the DNS A/AAAA record(s) for that domain
   contain(s) the right IP address.

お分かりと思いますが、「www.example.com」はダミーです。

実際にはちゃんとDNS設定を行ったドメインを指定しました。

エラーメッセージのとおり、Basic認証のせいでファイルを見られないということのようです。

というわけで、certbotが認証に利用するファイルへのアクセスだけBasic認証を除外することにしました。

調べてみると、acme-challengeのディレクトリを作っておいて、そこに.htaccessファイルを設置する…という方法が紹介されていました。

問題発生の環境はVPSなので、Apacheの設定ファイル(今回はvirtualhost.conf)に設定を行うことに。.htaccessファイルに設定内容が分散するのを避けたかったのです。

<VirtualHost *:443>
  ServerName www.example.com
  DocumentRoot /var/www/public

  # Basic authentication
  <Directory "/var/www/public">
    AuthType Basic
    AuthName "Please Enter ID and pass"
    AuthUserFile /var/www/.htpasswd
    Require valid-user
    AllowOverride All
  </Directory>

  # Exclusions for certbot authentication
  <Directory "/var/www/public/.well-known/acme-challenge">
    Satisfy any
    order allow,deny
    allow from all
  </Directory>

  SSLCertificateFile /etc/letsencrypt/live/www.example.com/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/www.example.com/privkey.pem
</VirtualHost>

Apacheを再起動して再度certbotを実行したところ、エラーが解消しました。

$ sudo certbot certonly --dry-run --webroot -w /var/www/public -d www.example.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for www.example.com
Using the webroot path /var/www/public for all unmatched domains.
Waiting for verification...
Cleaning up challenges

IMPORTANT NOTES:
 - The dry run was successful.

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

Linuxでディスク空き容量を調べる:dfコマンド

サーバーの調査をするときに毎回忘れてしまいます。

以下は、初期設定のまま実験用に利用している某VPSでの実行結果です。

$ sudo df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        486M     0  486M   0% /dev
tmpfs           496M     0  496M   0% /dev/shm
tmpfs           496M   51M  446M  11% /run
tmpfs           496M     0  496M   0% /sys/fs/cgroup
/dev/vda2        99G  4.7G   90G   5% /
tmpfs           100M     0  100M   0% /run/user/1000

ちなみに、”disk freespace”の略らしいです。そろそろ覚えたいです。

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

「更新に失敗しました。返答が正しいJSONレスポンスではありません。」 — WordPressに記事保存できなくなるエラー

記念すべきウチイダのメモリークリップ1記事目が、まさかこのサイトのトラブルシュートになるとは思いもしませんでした…

このサイトはConoHa Wingで運用を開始しています。
さっそく1記事目を作成して公開ボタンを押してみたら、、、

「更新に失敗しました。返答が正しいJSONレスポンスではありません」

いきなりつまづきました。出だし最悪!

とりあえず落ち着いてググってみたところ、どうやら.htaccessの内容がおかしいのが原因になっているらしい。

ConoHaの管理画面から見てみたら、確かに.htaccessファイルがリストにありません。

.htaccessファイルが消えている…

「何もしてないのに壊れた」と言いたくなるところですが、なにか原因があったのでしょう。
いや、ほんとに心当たりはなくて、ConoHa Wingの管理画面上から、WordPressインストールをしただけのはずなのですが…

とりあえず解決策は判明したので、以下の内容で.htaccessを作ってアップロードしました。

#SITEGUARD_PLUGIN_SETTINGS_START
#SITEGUARD_PLUGIN_SETTINGS_END

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

.htaccessをアップロードしました

これで再度保存を試したところ、改善しました。

タイムゾーンがずれている気がするけど…サーバは国内じゃなかったっけ…

余談ですが、ConoHa WingのWeb管理画面すごいですね。
ファイルの編集に、ACE Editorまで使えるとは。。。

ちょっとしたテーマファイルやcssの書き換えくらいなら、わざわざエディタ開く必要もなさそうです。

というわけで、これからいろいろと記憶の片隅に留めておきたいことをメモしていきます。

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