BioErrorLog Tech Blog

試行錯誤の記録

Raspberry PiのGPIOピン配置を確認する

Raspberry PiのGPIOピン配置位置を確認する方法を整理します。

はじめに

Raspberry PiのGPIOピン配置は複雑です。
私は毎度ピン配置を調べてから作業しています。

ピン配置の調べ方をしばしば忘れてしまうので、備忘録を残します。


[関連記事] www.bioerrorlog.work

想定環境

Raspberry Pi 2/3/4 ではGPIOピン配置は同じ(40本)で、本記事ではこちらを想定します。

一方、Raspberry Pi 1 Model B+以前はピン配置が異なります(26本)。

Prior to the Pi 1 Model B+ (2014), boards comprised a shorter 26-pin header.

ドキュメントより

Raspberry PiのGPIOピン配置を確認する

GPIOピン配置を確認する方法は、ざっくり以下のふたつがあります。

  • pinoutコマンドで確認する
  • ドキュメントから確認する

pinoutコマンドで確認する

Raspberry Piのターミナルでpinoutコマンドを実行することで、ピン配置を簡単に確認することが出来ます。

pi@raspberrypi:~ $ pinout
,--------------------------------.
| oooooooooooooooooooo J8   +======
| 1ooooooooooooooooooo  PoE |   Net
|  Wi                    1o +======
|  Fi  Pi Model 4B  V1.2 oo      |
|        ,----. +---+         +====
| |D|    |SoC | |RAM|         |USB3
| |S|    |    | |   |         +====
| |I|    `----' +---+            |
|                   |C|       +====
|                   |S|       |USB2
| pwr   |hd|   |hd| |I||A|    +====
`-| |---|m0|---|m1|----|V|-------'

Revision           : c03112
SoC                : BCM2711
RAM                : 4GB
Storage            : MicroSD
USB ports          : 4 (of which 2 USB3)
Ethernet ports     : 1 (1000Mbps max. speed)
Wi-fi              : True
Bluetooth          : True
Camera ports (CSI) : 1
Display ports (DSI): 1

J8:
   3V3  (1) (2)  5V
 GPIO2  (3) (4)  5V
 GPIO3  (5) (6)  GND
 GPIO4  (7) (8)  GPIO14
   GND  (9) (10) GPIO15
GPIO17 (11) (12) GPIO18
GPIO27 (13) (14) GND
GPIO22 (15) (16) GPIO23
   3V3 (17) (18) GPIO24
GPIO10 (19) (20) GND
 GPIO9 (21) (22) GPIO25
GPIO11 (23) (24) GPIO8
   GND (25) (26) GPIO7
 GPIO0 (27) (28) GPIO1
 GPIO5 (29) (30) GND
 GPIO6 (31) (32) GPIO12
GPIO13 (33) (34) GND
GPIO19 (35) (36) GPIO16
GPIO26 (37) (38) GPIO20
   GND (39) (40) GPIO21

POE:
TR01 (1) (2) TR00
TR03 (3) (4) TR02

For further information, please refer to https://pinout.xyz/


ドキュメントから確認する

Raspberry Piにログインしているときは先述のpinoutコマンドを実行するのが簡単ですが、普通にドキュメントから調べることもできます。

Rapsberry Pi公式ドキュメントでは、GPIOピン配置や各ハードウェア仕様を確認できます:


pinout.xyzからもGPIOピン配置を確認できます。

先述のpinoutコマンドで参考URLに指定されていたのは、こちらのサイトの方ですね。

# pinout コマンド出力結果最終行
For further information, please refer to https://pinout.xyz/

おわりに

今回は、Raspberry PiのGPIOピン配置を確認する方法をメモしました。

ピンの場所は油断するとすぐ間違えがちなので、気を付けて作業したいものです。 ピン配置が記載されたカードを装着することも考えた方がよいかもしれません。

このメモがどなたかの参考になれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

Raspberry Pi GPIO Pinout

documentation/using-gpio.adoc at develop · raspberrypi/documentation · GitHub

Raspberry Pi Documentation - Raspberry Pi OS

GPIO Pin Numbering - Raspberry Pi Forums

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

Raspberry Pi OSにDockerをインストールする方法をまとめます。

はじめに

こんにちは、@bioerrorlogです。

先日、Raspberry Pi 4を購入しました。

Raspberry Piで色々と遊んでいると、Dockerもインストールしてみたくなりました。

今回はそのインストール方法をまとめます。

前提

使用機器:Raspberry Pi 4

Raspberry Pi OSが動作済みで、ディスプレイ/キーボード接続またはSSH接続によってRaspberry Pi OSのターミナルが操作できる状態を前提としています。

Raspberry Pi OSのセットアップにはこちらも参考にしてください: www.bioerrorlog.work

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

以下の手順でDockerをインストールしていきます。

  1. OSアップデート
  2. Dockerのダウンロード/インストール
  3. Dockerインストールの確認
  4. ユーザにDockerへの権限を付与
  5. 再起動
  6. 動作確認:hello-worldコンテナを動かす

1. OSアップデート

まず、以下のコマンドでOSをアップデート/アップグレードして最新の状態に更新します。

sudo apt update && sudo apt upgrade

2. Dockerのダウンロード/インストール

Docker公式が提供しているインストールスクリプトを取得/実行して、Dockerをインストールします。

curl -sSL https://get.docker.com | sh

3. Dockerインストールの確認

docker --versionを実行し、Dockerが無事インストールされたことを確認します。

$ docker --version
Docker version 20.10.7, build f0df350

4. ユーザにDockerへの権限を付与

Dockerをインストールした直後の状態では、ユーザにDocker実行の権限がありません。 毎回sudoで実行する必要があります。

これを解消するために、ユーザにDocker実行の権限を付与(dockerグループに追加)します。

sudo usermod -aG docker ${USER}

${USER}は、現在のユーザを指し示す変数です。 ユーザ名を直接指定しても同じく権限を付与することが出来ます。

sudo usermod -aG docker [user_name]

5. 再起動

ユーザへのDocker実行権限付与を反映させるため、Raspberry Piを再起動します。

6. 動作確認:hello-worldコンテナを動かす

ここまでの手順で、Dockerのインストールとユーザへの実行権限付与が出来ました。

最後にhello-worldコンテナを実行して、Dockerが実行できることを確認します。

$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2c7ed585684a: Pull complete 
Digest: sha256:df5f5184104426b65967e016ff2ac0bfcd44ad7899ca3bbcf8e44e4461491a9e
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm32v7)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

上記のようにhello-worldコンテナが実行できれば成功です。

おわりに

今回は、Raspberry PiにDockerをインストールする方法をまとめました。

Raspberry Pi OSのアーキテクチャ(Arm32)には気を付ける必要がありますが、これでコンテナをRaspberry Piで動かすことが出来るようになりました。

どんな使い方が出来るか、想像が膨らみます。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

How To Install Docker and Docker-Compose On Raspberry Pi - DEV Community 👩‍💻👨‍💻

Docker comes to Raspberry Pi - Raspberry Pi

Raspberry Piを購入してセットアップする | Raspberry Pi入門

Raspberry Pi 4とその周辺パーツの購入から、Raspberry Pi OS起動までの作業をまとめます。

はじめに

こんにちは、@bioerrorlogです。

先日、Raspberry Piを買ってきました。

私はRaspberry Piはもちろん、電子工作的なものにも経験ありません。 新しい世界にワクワクしてます。

本記事では、Raspberry Pi 4とその周辺パーツの購入から、Raspberry Pi OS起動までを記録します。

Raspberry Piを購入してセットアップする

Raspberry Piとその周辺パーツの購入

まず、Raspberry Pi 4と周辺パーツを購入します。

Raspberry Pi 2や3など他のバージョンで必要なパーツと、Raspberry Pi 4で必要なパーツは異なります。

ネット上の情報を参考にする場合は、その記事がどのバージョンのRaspberry Piに言及しているのかに注意してください。 本記事ではRaspberry Pi 4を使います。

必要なもの:

  • Raspberry Pi 4 (筆者はModel B 4GB RAMを購入)
  • USB-C 電源コード (出力 3A, 5Vほど)
  • microSDカード (容量8GB以上、Class10のものが良い)
  • microSDカードアダプタ (microSDにPCからデータを書き込む用)
  • USBキーボード (有線)
  • USBマウス (有線)
  • micro HDMIケーブル (Raspberry Pi側がmicro HDMI)
  • ディスプレイ

ディスプレイは既に持っているものがあれば、使いまわして大丈夫です。

これらパーツを、ネットでもリアル店舗でもよいので購入します。

私は以下の秋葉原の電気屋を巡って購入しました。 ネットでポチるのも良いですが、実物を見ながら買うのもまた一興です。 東京にいる方は参考にしてみてください。

microSDカードのセットアップ

パーツが揃ったら、Raspberry Pi Imagerを使ってmicroSDにRaspberry Pi OSを書き込みます。

Raspberry Pi Imagerとは、Raspberry Pi OSをmicroSDに自動でインストールしてくれるアプリケーションです。 書き込み後のmicroSDをRaspberry Piに挿して電源を付ければ、OSを起動することが出来ます。

Raspberry Pi Imager is the quick and easy way to install Raspberry Pi OS and other operating systems to a microSD card, ready to use with your Raspberry Pi.

公式の説明より


以下の手順でmicroSDに書き込んでいきます。

今回私はWindows PCを使っていますが、MacやLinux (Ubuntu)でも同様の操作が可能です。


1.Raspberry Pi Imagerのインストーラをダウンロード

Raspberry Pi OS – Raspberry Pi

上記リンクから、PCのOSに合ったRaspberry Pi Imagerのインストーラをダウンロードします。


2.Raspberry Pi Imagerをインストール

ダウンロードしたRaspberry Pi Imagerのインストーラをダブルクリックし、画面に従ってインストールを進めます。

"Install" をクリック

"Finish" をクリック


3.Raspberry Pi ImagerでmicroSDに書き込み

Raspberry Pi Imagerのインストールが終わると、ウィンドウが自動で立ち上がります。 立ち上がったら、下記の手順でmicroSDにRaspberry Pi OSを書き込んでいきます。

起動画面でCHOOSE OSを選択


Raspberry Pi OS (32-bit)を選択


"CHOOSE STORAGE"からSDカードを選択


書き込み終了


書き込みが終了したらmicroSDを取り出し、Raspberry Piの起動に移ります。

Raspberry Piの起動

Raspberry Piを起動するには、順番に各部品を取り付けてから電源コードを挿入します。

1.microSDを挿入

microSDを挿入する | 画像は公式チュートリアルより


2.USBマウス・USBキーボードを取り付け

マウス・キーボードを取り付ける | 画像は公式チュートリアルより


3.micro HDMIディスプレイを取り付け

ディスプレイを取り付ける | 画像は公式チュートリアルより


4.電源コードを取り付け

電源コードを取り付ける | 画像は公式チュートリアルより改変


電源コードを取り付けると、自動でOSが立ち上がります。

Raspberry Pi OSの起動後画面 | 画像は公式チュートリアルより

これで、今回の目的は達成しました。

おわりに

今回は、Raspberry Pi 4とその周辺パーツを揃えてOSを起動するまでの作業をまとめました。

今後もRaspberry Piで遊びながら、作業記録を記事に残していこうと思います。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

Projects | Computer coding for kids and teens | Raspberry Pi

Raspberry Pi OS – Raspberry Pi

パイプ処理の終了ステータスを取得する | Linux shell

パイプ処理の終了ステータスを取得する方法をまとめます。

はじめに

こんにちは、@bioerrorlogです。

パイプ処理の終了ステータスを取得($?)すると、デフォルトでは一番最後のコマンドの終了ステータスのみが取得されます。

#!/bin/bash

exit 1 | exit 2 | exit 0
echo $? # 出力: 0

パイプ内コマンドの終了ステータスはマスクされてしまうので、パイプ内の異常終了を検知したいときなどに不都合です。

今回は、パイプ処理内の各コマンドの終了ステータスを取得する方法をまとめます。

環境

bashでの実行を前提としています。

パイプ処理の終了ステータスを取得する

PIPESTATUS を参照する方法

まずは、PIPESTATUSを使った方法です。 この変数には、実行されたパイプ処理内コマンドの終了ステータスが配列で格納されます。

${PIPESTATUS[@]}で参照すれば、パイプ処理内の全コマンドの終了ステータスが確認できます。

#!/bin/bash

exit 1 | exit 2 | exit 0
echo "${PIPESTATUS[@]}" # 出力: 1 2 0


引数を渡して参照すれば、特定のパイプ処理内コマンドの終了ステータスを取得できます。

#!/bin/bash

exit 1 | exit 2 | exit 0
echo "${PIPESTATUS[0]}" "${PIPESTATUS[1]}" # 出力: 1 2

set -o pipefail を利用した方法

次はset -o pipefailを利用した方法です。

set -o pipefailは、0以外の終了ステータスで終えた最後のコマンドの終了ステータスを、パイプ処理の終了ステータスとする設定です。 パイプ内コマンドの異常終了ステータスをマスクせずに取得することが出来るようになります。

setコマンドのman pageより引用:

the return value of a pipeline is the status of the last command to exit with a non-zero status, or zero if no command exited with a non-zero status


実際に実行してみると、以下のようにパイプ内の最後の異常終了ステータスが、パイプの終了ステータスとして取得されます。

#!/bin/bash

set -o pipefail
exit 1 | exit 2 | exit 0
echo $? # 出力: 2

おわりに

今回は、パイプ処理の終了ステータスを取得する方法をまとめました。

パイプ処理は非常に強力な機能なので、細かいハンドリングも含めて使い慣れていきたいものです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

参考

shell - Get exit status of process that's piped to another - Unix & Linux Stack Exchange

set -e, -u, -o, -x pipefail explanation · GitHub

set man page

JSONのレコード件数をjqコマンドでカウントする | Linux shell

JSON形式ごとにjqコマンドでレコード件数をカウントする方法をまとめます。

はじめに

こんにちは、@bioerrorlogです。

先日、LinuxコマンドラインでJSONのレコード件数をカウントすることがありました。 csvファイルであれば行数をカウントすれば済みますが、JSONの場合は記述形式によってカウント方法を工夫する必要があります。

今回は、jqコマンドを用いたJSON形式ごとのレコード数カウント方法をまとめます。

環境

OS: Amazon Linux 2で動作を確認しています。

JSONのレコード件数をカウントする

3つのJSON形式のレコード件数カウント方法を見ていきます。

  • 配列括りのJSON Document
  • オブジェクト括りのJSON Document
  • JSON Lines

配列括りのJSON Document

# array.json
[
  {"id":1,"name":"aaa"},
  {"id":2,"name":"bbb"},
  {"id":3,"name":"ccc"},
  {"id":4,"name":"ddd"},
  {"id":5,"name":"eee"}
]

上記のような配列括りのJSONarray.jsonのレコード数をカウントするには、以下のコマンドを実行します。

cat array.json | jq 'length'
# 出力: 5

このコマンドではまず、catコマンドでJSONファイルの中身をパイプ|jqコマンドに渡します。
そしてjqコマンドではフィルタにlengthを適用し、レコード件数を取得します。

jqコマンドのビルトイン関数であるlengthは、渡された値の形式に応じて要素数を返します。 配列が渡された場合は、配列の要素数を返します。
jq manページ より:

length
  The builtin function length gets the length of various different types of value:
   ·  The length of a string is the number of Unicode codepoints it contains (which will be the same as its JSON-encoded length in bytes if it´s pure ASCII).
   ·  The length of an array is the number of elements.
   ·  The length of an object is the number of key-value pairs.
   ·  The length of null is zero.

オブジェクト括りのJSON Document

# object.json
{
  "records": [
    {"id":1,"name":"aaa"},
    {"id":2,"name":"bbb"},
    {"id":3,"name":"ccc"},
    {"id":4,"name":"ddd"},
    {"id":5,"name":"eee"}
  ]
}

上記のようなオブジェクト括りのJSONobject.jsonに対し、"records"に格納された配列内のレコード数をカウントするには、以下のコマンドを実行します。

cat objects.json | jq '.records | length'
# 出力: 5

このコマンドでは、jqコマンドのフィルタとして'.records | length'を適用しています。

まずフィルタ.recordsで"records"に格納された配列を取り出した後、lengthフィルタを適用することで配列の要素数がカウントできます。

JSON Lines

# lines.json
{"id":1,"name":"aaa"}
{"id":2,"name":"bbb"}
{"id":3,"name":"ccc"}
{"id":4,"name":"ddd"}
{"id":5,"name":"eee"}

上記のようなJSON Lines形式のファイルlines.jsonのレコード件数を取得するには、以下のコマンドを実行します。

cat lines.json | jq -s 'length'
# 出力: 5

まず、jqコマンドに-s/--slurpオプションを付与することで、以下のように入力全体が一つの配列に格納される形で出力されます。

$ cat lines.json | jq -s
[
  {
    "id": 1,
    "name": "aaa"
  },
  {
    "id": 2,
    "name": "bbb"
  },
  {
    "id": 3,
    "name": "ccc"
  },
  {
    "id": 4,
    "name": "ddd"
  },
  {
    "id": 5,
    "name": "eee"
  }
]

これに対してlengthフィルタを適用することで、レコード件数を取得することが出来ます。

※ ちなみに、例えばインプットファイルが以下のように適当に改行を含んでいても問題なく機能します。

# lines.json
{
  "id":1,
  "name":"aaa"}
{"id":2,"name":"bbb"}
{"id":3,
"name":"ccc"}
{
  "id":4,
  "name":"ddd"
}
{"id":5,"name":"eee"
}

レコード件数カウント:

cat lines.json | jq -s 'length'
# 出力: 5

おわりに

今回は、jqコマンドを用いてJSONのレコード件数をカウントする方法をまとめました。

JSONファイルは多様な記述方法があるので、何か処理を適用するときはインプットファイルの形式に注意する必要があります。

いずれのJSON形式でもjqコマンドなら柔軟に対応できるので、上手く活用していきたいところです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

参考

jq Manual (development version)

bash - How to count items in JSON object using command line? - Stack Overflow

JSON Lines

JSON Schema: A Media Type for Describing JSON Documents

JSON - Wikipedia

Pythonでメモリ/ディスク容量を確認する

Pythonを用いて、実行環境のメモリおよびディスク容量を確認する方法を整理します。

はじめに

Pythonを用いて、実行環境のメモリおよびディスク容量を確認する必要に迫られました。

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

# 作業環境
OS: Linux (Amazon Linux 2)  
Python 3.8

ディスク/メモリ容量を取得する

ディスク容量

ディスク容量を確認するには、以下のコードを実行します。

import shutil

total, used, free = shutil.disk_usage('/')

print(f'Total: {total / (2**30)} GiB')
print(f'Used: {used / (2**30)} GiB')
print(f'Free: {free / (2**30)} GiB')

# 10の9乗をギガとする場合
# print(f'Total: {total / (10**9)} GB')
# print(f'Used: {used / (10**9)} GB')
# print(f'Free: {free / (10**9)} GB')

Pythonの標準ライブラリshutilを用いて、ディスク容量を確認します。

shutil.disk_usage(path)path部分に任意のパスを与えることで、そのパス割り当てのディスク総量/使用済み容量/空き容量を取得できます。

※shutil.disk_usageのドキュメント

Return disk usage statistics about the given path as a named tuple with the attributes total, used and free, which are the amount of total, used and free space, in bytes. path may be a file or a directory.

メモリ容量

物理メモリ容量を確認するには、以下のコードを実行します。

import os
mem_bytes = os.sysconf('SC_PAGE_SIZE') * os.sysconf('SC_PHYS_PAGES')
print(f'Memory total: {mem_bytes / (2**30)} GiB')

# 10の9乗をギガとする場合
# print(f'Memory total: {mem_bytes / (10**9)} GB')

メモリのページサイズos.sysconf('SC_PAGE_SIZE')と、物理メモリのページ数os.sysconf('SC_PHYS_PAGES')から、物理メモリの総容量が算出できます。

※Windows環境ではこのsysconfメソッドは利用できないのでご注意ください。

おわりに

以上、Pythonでメモリおよびディスク容量を調べる方法を記しました。

ローカルの端末あるいは普通のサーバであれば、システム情報やターミナルからメモリ/ディスク容量を確認できるかと思います。 ただ、何かの事情でPythonの実行環境しか渡されない場合、Pythonからこれら情報を取得する必要がでてきます。

そうしたケースの参考になれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

macos - Get hard disk size in Python - Stack Overflow

linux - Get total physical memory in Python - Stack Overflow

shutil — High-level file operations — Python 3.11.4 documentation

os — Miscellaneous operating system interfaces — Python 3.11.4 documentation

sysconf(3): config info at run time - Linux man page

Session Managerで自動実行コマンドを設定する | AWS Systems Manager

Session Managerでセッション開始時の自動実行コマンド(shell profiles)を指定する方法と、その利用例を整理します。

はじめに

こんにちは、@bioerrorlogです。

AWS Systems Manager(SSM)のSession ManagerでEC2インスタンスに接続すると、カレントディレクトリが/usr/binだったり、デフォルトのshellがbashでなくBourne shellだったりと、少し不便なことがあります。

これら接続時のデフォルト設定を変更するために、セッション開始時の自動実行コマンド(shell profiles)を指定する方法を整理します。

環境

EC2インスタンス: Amazon Linux 2
SSM agent version: 3.0.655.0

Session Managerの自動実行コマンドを設定する

自動実行コマンド(shell profiles)の設定方法

最初に、自動実行コマンドの設定方法を確認します。

まず、Systems Managerのマネジメントコンソールから、"セッションマネージャー"を選択します。


次に、"設定"タブを選択し、"編集"ボタンをクリックします。


下の方にスクロールし、"Linux shell profile"の欄に任意のコマンドを入力します(Windowsインスタンスの場合は、その下の"Windows shell profile"の欄に入力します)。


これで、上記の欄に記入されたコマンドがセッション開始時に実行されます。

それでは、以下に利用例を挙げていきます。

利用例) デフォルトshellをbashにする

Session Manager接続時には、デフォルトのshellがbashでなくBourne shellになっています。 以下のように接続画面でsh-4.2$と表示されているのがそれです。

sh-4.2$

これをデフォルトでbashにするには、"Linux shell profile"にbashコマンドを設定しておきます。

bash

これで、以下のようにセッション開始時からbashが指定された状態になります。

[ssm-user@ip-172-31-14-102 bin]$

利用例) カレントディレクトリを変更する

セッション開始時のカレントディレクトリは、デフォルトで/usr/binになっています。

sh-4.2$ pwd
/usr/bin

これをあらかじめ変更させておくには、"Linux shell profile"でcdコマンドを設定しておきます。 例えばユーザーディレクトリをデフォルトのカレントディレクトリとするには、以下のようにコマンドを設定しておきます。

cd ~

これで、ユーザーディレクトリに移動した状態から作業を始めることが出来ます。

sh-4.2$ pwd
/home/ssm-user

利用例) ログインユーザーを変更する

Session Managerでは、デフォルトでユーザーssm-userとして接続されています。

sh-4.2$ whoami
ssm-user

このログインユーザをあらかじめ変更させるには、"Linux shell profile"でsuコマンドを設定します。 例えばrootとしてログインしたいのであれば、以下のように設定しておきます。

sudo su -

これで、rootユーザーとして作業を始めることが出来ます。

[root@ip-172-31-14-102 ~]# whoami
root


これら以外にも任意のコマンドを組み合わせて、接続時の状態を自由に設定することが出来ます。

おわりに

今回は、Session Managerで自動実行コマンド(shell profiles)を設定する方法をその利用例を整理しました。

Session Managerは接続時の状態に何かと不便なことがあるので、これを利用すれば少しでもフラストレーションを緩和することが出来ます。

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

[関連記事]
www.bioerrorlog.work

www.bioerrorlog.work

参考

Allow configurable shell profiles - AWS Systems Manager

Session Managerの"sh-4.2$"をbashに切り替える | AWS Systems Manager

Session Managerで表示される sh-4.2$の正体と、それをbashに切り替える方法の備忘録です。

はじめに

こんにちは、@bioerrorlogです。

AWS Systems Manager(SSM)のSession ManagerでEC2インスタンスに接続すると、最初に以下のような画面が表示されます。

sh-4.2$

何か、見慣れたLinuxターミナル画面とは違うなとずっと思っていました。

Linux EC2インスタンスで見慣れたshell画面は、例えば次のようなものです。

[ec2-user@ip-172-31-14-102 ~]$

今回は、このsh-4.2$の正体と、それを見慣れたbashに切り替える方法を整理します。

環境

EC2インスタンス: Amazon Linux 2
SSM agent version: 3.0.161.0

Session Managerの"sh-4.2$"をbashに切り替える

sh-4.2$の正体は何か

まずsh-4.2$の正体ですが、これはBourne shell (sh)と呼ばれるもので、普段使われるbashとは異なるものです。

Session ManagerでLinux EC2インスタンスに接続した際には、デフォルトでこのBourne shellが設定されています。

SSMドキュメントにも、以下のように記載があります。

By default, sessions on EC2 instances for Linux start using the Bourne shell (sh).

このBourne shellをbashに切り替えてあげれば、見慣れた形で作業が出来そうです。

bashに切り替える方法

ではどうやってbashに切り替えるのか?

やり方は簡単で、bashとコマンドに打てばbashに切り替わります。

sh-4.2$ bash
[ssm-user@ip-172-31-14-102 bin]$

これで、bashで実行できるようになりました。


逆にBourne shellに戻すには、shと打ちます。

[ssm-user@ip-172-31-14-102 bin]$ sh
sh-4.2$

おわりに

以上、Session Managerで表示される sh-4.2$の正体と、それをbashに切り替える方法をメモしました。

これまではBourne shellの存在を知らないままモヤモヤしていましたが、Bourne shellとbash shellの切り替えを知ってスッキリしました。

誰かの役に立てば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

参考

Allow configurable shell profiles - AWS Systems Manager

bash - Linux difference between root shell "#" and "sh-4.2 #" - Stack Overflow

How to use common workflows on Amazon SageMaker notebook instances | AWS Machine Learning Blog

Bourne shell - Wikipedia

bash(1) - Linux manual page

aws s3 cpコマンドで標準入出力をデータ出力/入力先に指定する | AWS CLI

AWS CLIのs3 cpコマンドにて、データの出力/入力先に標準入出力を指定する方法の備忘録です。

はじめに

こんにちは、@bioerrorlogです。

AWS CLIのs3 cpコマンドは、s3のオブジェクトをコピーできる便利なコマンドです。 主に以下のようにして使います。

aws s3 cp [コピー元 localパス/S3 URI] [コピー先 localパス/S3 URI]

先日、このコピー元/コピー先のパスとして、標準入出力を指定できることを知りました。

今回は、そのやり方をメモします。

環境

今回の作業環境は以下です:

aws-cli: 2.1.16
OS: Amazon Linux 2

cpコマンドで標準入出力を活用する

標準入出力の指定方法

まず結論から、コピー元/コピー先のパスに標準入出力を指定するには - を指定します。

例えば、S3上のオブジェクトの中身を標準出力に表示するには以下のようなコマンドを実行します。

aws s3 cp s3://bucket-name/object.txt -


ドキュメントにも、以下のように記載されています。

標準入力:

The following cp command uploads a local file stream from standard input to a specified bucket and key:
aws s3 cp - s3://mybucket/stream.txt


標準出力:

The following cp command downloads an S3 object locally as a stream to standard output. Downloading as a stream is not currently compatible with the --recursive parameter:
aws s3 cp s3://mybucket/stream.txt -

上記にも記載があるように、--recursiveパラメータを指定して標準出力にデータを出力することはできませんので、そこは注意が必要です。

具体例

では、実際にいくつか利用例を示します。

まず、単純にS3オブジェクト内容を標準出力に表示させまてみます。

$ aws s3 cp s3://target-bucket-001/abc.txt -
aaa
bbb
ccc

S3に配置したファイル内容がそのまま標準出力に表示されました。


標準入出力を使えるということは、パイプで別コマンドと自由に処理をつなげることもできます。

$ aws s3 cp s3://target-bucket-001/abc.txt.gz - | gunzip | grep "ccc"
ccc

上記コマンド例では、gzip圧縮されたS3ファイルを解凍->検索しています。


パイプでS3オブジェクトの出力->入力を繋げれば、1ラインでS3に再格納することもできます。

$ aws s3 cp s3://target-bucket-001/abc.txt.gz - | gunzip |  aws s3 cp - s3://target-bucket-001/gunzip_abc.txt


このように、標準入出力を利用して自由にファイルを処理出来ます。

おわりに

今回は、aws s3 cpコマンドで標準入出力を利用する方法を簡単にメモしました。

ちょっとしたTipsではありますが、パイプもうまく利用すればなかなか強力な手段になると思います。

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

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

参考

cp — AWS CLI 1.25.76 Command Reference

AWS Command line: S3 content from stdin or to stdout

amazon web services - How to use AWS S3 CLI to dump files to stdout in BASH? - Stack Overflow

whoisエラー対処 | No whois server is known for this kind of object.

whoisコマンド実行時に以下のエラーが出たときの対処法です。

No whois server is known for this kind of object.


はじめに

おはよう。@bioerrorlogです。

当ブログのドメインbioerrorlog.workに対してwhoisコマンドを実行したところ、以下のエラーを吐かれてしまいました。

$ whois bioerrorlog.work
No whois server is known for this kind of object.

該当するwhoisサーバーが見つからない、怒られています。 .workドメインは比較的新しいため、このようなエラーが吐かれているのでしょう。

このエラーに対する対処法を書きます。


作業環境

  • OS: Amazon Linux 2
  • whoisバージョン: Version 5.1.1.


エラー対処

接続先ホストを特定する

解決策としては、接続先として然るべきホストを-hオプションに指定してwhoisコマンドを実行することが挙げられます。

whois -h [接続先whoisホスト] bioerrorlog.work

そのためにまず、以下のコマンドで接続先ホストを調べます。

whois -h whois.iana.org .work |
  egrep -e '^whois:' |
  sed -e 's/[[:space:]][[:space:]]*/ /g' |
  cut -d " " -f 2

1行目の.work部分は、調べたいドメインに合わせて変更してください。

この例では、.workドメインに対するwhoisサーバーが以下のように返されます。

whois.nic.work


上記コマンドで行っている処理をひとつひとつ見ていきます。


  • 1行目
whois -h whois.iana.org .work

最初は、調べたいドメイン.workを、IANAに対して直接whoisします。 これにより、.workドメインのwhoisサーバー名を含む情報が以下のように得られます。

$ whois -h whois.iana.org .work
% IANA WHOIS server
% for more information on IANA, visit http://www.iana.org
% This query returned 1 object

domain:       WORK

organisation: Minds + Machines Group Limited
address:      Craigmuir Chambers, Road Town Tortola VG 1110
address:      Virgin Islands, British

contact:      administrative
name:         Admin Contact
organisation: Minds + Machines Ltd
address:      32 Nassau St, Dublin 2
address:      Ireland
phone:        +1-877-734-4783
e-mail:       ops@mmx.co

contact:      technical
name:         TLD Registry Services Technical
organisation: Nominet
address:      Minerva House,
address:      Edmund Halley Road,
address:      Oxford Science Park,
address:      Oxford,
address:      OX4 4DQ
address:      United Kingdom
phone:        +44.1865332211
e-mail:       registrytechnical@nominet.uk

nserver:      DNS1.NIC.WORK 213.248.217.35 2a01:618:401:0:0:0:0:35
nserver:      DNS2.NIC.WORK 103.49.81.35 2401:fd80:401:0:0:0:0:35
nserver:      DNS3.NIC.WORK 213.248.221.35 2a01:618:405:0:0:0:0:35
nserver:      DNS4.NIC.WORK 2401:fd80:405:0:0:0:0:35 43.230.49.35
nserver:      DNSA.NIC.WORK 156.154.100.3 2001:502:ad09:0:0:0:0:3
nserver:      DNSB.NIC.WORK 156.154.101.3
nserver:      DNSC.NIC.WORK 156.154.102.3
nserver:      DNSD.NIC.WORK 156.154.103.3
ds-rdata:     7331 8 2 F6EBBE59BD6CF2D7D8F6AD1A31F38E84BE3C4613432E59703C4D90BC8D47E1C1

whois:        whois.nic.work

status:       ACTIVE
remarks:      Registration information: http://mm-registry.com/

created:      2014-08-18
changed:      2019-08-22
source:       IANA


  • 2行目
egrep -e '^whois:'

こちらでは、1行目の実行結果から"whois:"で始まる行を抽出しています。 ここまでで、以下の結果が得られます。

$ whois -h whois.iana.org .work |
>   egrep -e '^whois:'
whois:        whois.nic.work


  • 3行目
sed -e 's/[[:space:]][[:space:]]*/ /g'

次は、こちらのsedコマンドによって、連続したスペースを排除しています。

-eオプションに指定されたパラメータ:s/[regexp]/[replacement]/gによって、[regexp]に一致する部分が[replacement]で全て(gフラッグ)置換されます。 ここまでで、以下の結果が得られます。

$ whois -h whois.iana.org .work |
>   egrep -e '^whois:' |
>   sed -e 's/[[:space:]][[:space:]]*/ /g'
whois: whois.nic.work


  • 4行目
cut -d " " -f 2

最後はcutコマンドで、必要な部分を抜粋します。 -dオプションで区切り文字にスペースを指定し、
-fオプションでその2項目目を抽出しています。

以上により、以下のwhoisサーバー名が得られます。

$ whois -h whois.iana.org .work |
>   egrep -e '^whois:' |
>   sed -e 's/[[:space:]][[:space:]]*/ /g' |
>   cut -d " " -f 2
whois.nic.work


ホストを指定してwhoisコマンドを実行する

ここまでくればあとは簡単です。 前述のコマンドで得られたwhoisサーバーをホスト-hに指定して、目的のドメインbioerrorlog.workをwhoisします。

whois -h whois.nic.work bioerrorlog.work

whois.nic.work部分は前章の手順で得られたwhoisサーバー名を、
bioerrorlog.workはwhois対象のドメインに置き換えてください。

これで、エラーなくwhois情報を取得できました。


おわりに

今回は、whoisコマンドが実行できない時の対処法を書きました。

最近の新しいドメインを調べる際には、同じようなエラーに遭遇するのではないかと思います。

そのような方の参考になれば幸いです。


[関連記事] ある文字列を含むファイルをgrepコマンドで検索する | Linux


参考

linux - How to whois new TLDs? - Super User

Internet Assigned Numbers Authority - Wikipedia

The s Command - gnu.org

sed コマンド | コマンドの使い方(Linux) | hydroculのメモ

S3既存オブジェクトに一括でbucket-owner-full-controlを付与する | AWS CLI

S3バケットの既存の全オブジェクトに--acl bucket-owner-full-controlを一括付与するやり方の備忘録です。


はじめに

おはよう。@bioerrorlogです。

クロスアカウントのS3間でオブジェクトをコピーするとき、--acl bucket-owner-full-controlを付与せずにそのままアップロードしてしまうと、アップロード先のアカウント側からアクセスできなくなることが知られています


f:id:BioErrorLog:20201102184648p:plain
--acl bucket-owner-full-controlを付与せずにクロスアカウントS3アップロードすると、アップロード先のアカウントからアクセスできない

この問題を事前に回避するには、オブジェクトコピー時に--acl bucket-owner-full-controllを付与したり、コピー先のS3バケットでObject Ownershipを設定したりする方法が挙げられます。

一方、オブジェクトコピー後にこの問題を解消するには、put-object-aclコマンドを用いて後からbucket-owner-full-controlを付与する方法があります。

aws s3api put-object-acl --bucket destination_awsexamplebucket --key keyname --acl bucket-owner-full-control

※コマンドはオブジェクトコピー元アカウントの権限で実行する必要があります。

しかし、このコマンドはS3オブジェクト1つに対して実行するものであり、特定ディレクトリやバケット全体を指定することはできません。 そうしたい場合には、ちょっとした工夫が必要になります。

今回はそのような、特定ディレクトリやバケット全体を指定して--acl bucket-owner-full-controlを一括付与するやり方を記します。


既存オブジェクトにbucket-owner-full-controllを一括付与する

結論として、以下のコマンドを実行します。

aws s3 ls s3://target-bucket/ --recursive | awk '{print $4}' | xargs -I KEY aws s3api put-object-acl --bucket target-bucket --key "KEY" --acl bucket-owner-full-control

(コマンドはこちらを参考/改変しています)


※追記: 上記コマンドは、オブジェクトキーに日本語が入っていたり、スペースが入っていたりすると上手く機能しません。 代わりに以下のコマンドの方がお勧めです。

aws s3api list-objects-v2 --bucket target-bucket | jq .Contents[].Key | xargs -I KEY aws s3api put-object-acl --bucket target-bucket --key "KEY" --acl bucket-owner-full-control


これは3つのコマンドをパイプで繋げたものであり、指定したS3バケット/ディレクトリ以下にあるオブジェクト全てにbucket-owner-full-controlを付与しています。

以下、上記コマンドを旧バージョンのものと追記バージョンのものとで、それぞれひとつひとつ見ていきます。


追記バージョンコマンドの解説

aws s3api list-objects-v2 --bucket target-bucket | jq .Contents[].Key | xargs -I KEY aws s3api put-object-acl --bucket target-bucket --key "KEY" --acl bucket-owner-full-control

まず、こちら追記バージョンコマンドの解説をします。


aws s3api list-objects-v2 --bucket target-bucket

まずはこちらlist-objects-v2コマンドにより、以下のようにバケットのオブジェクトリストを取得します。

$ aws s3api list-objects-v2 --bucket target-bucket
{
    "Contents": [
        {
            "LastModified": "2020-11-02T12:45:17.000Z", 
            "ETag": "\"47bce5c74f589f4867dbd57e9ca9f808\"", 
            "StorageClass": "STANDARD", 
            "Key": "aaa.txt", 
            "Size": 3
        }, 
        {
            "LastModified": "2020-11-02T12:45:17.000Z", 
            "ETag": "\"585cc54d19a29743e94948bf6d3a4592\"", 
            "StorageClass": "STANDARD", 
            "Key": "bbb.txt", 
            "Size": 12
        }, 
        {
            "LastModified": "2020-11-02T12:45:17.000Z", 
            "ETag": "\"9df62e693988eb4e1e1444ece0578579\"", 
            "StorageClass": "STANDARD", 
            "Key": "ccc.txt", 
            "Size": 3
        }, 
        {
            "LastModified": "2020-11-02T12:45:17.000Z", 
            "ETag": "\"47bce5c74f589f4867dbd57e9ca9f808\"", 
            "StorageClass": "STANDARD", 
            "Key": "ddd.txt", 
            "Size": 3
        }, 
        {
            "LastModified": "2020-11-02T12:45:17.000Z", 
            "ETag": "\"585cc54d19a29743e94948bf6d3a4592\"", 
            "StorageClass": "STANDARD", 
            "Key": "eee.txt", 
            "Size": 12
        }, 
        {
            "LastModified": "2020-11-02T12:45:17.000Z", 
            "ETag": "\"9df62e693988eb4e1e1444ece0578579\"", 
            "StorageClass": "STANDARD", 
            "Key": "fff.txt", 
            "Size": 3
        }
    ]
}

なお、取得範囲を特定パスに絞りたいときは、--prefixオプションを使用します。


次に、上記実行結果をjqコマンドで処理します。

jq .Contents[].Key

jqは、jsonから値を抽出できるコマンドです。 上記コマンドにより、オブジェクトリストのうちオブジェクトキーを抽出します。

$ aws s3api list-objects-v2 --bucket target-bucket-001 | jq .Contents[].Key                                                                                                                                             
"aaa.txt"
"bbb.txt"
"ccc.txt"
"ddd.txt"
"eee.txt"
"fff.txt"

これでちょうど、オブジェクトキーが出力される形になります。


最後にこの出力を受け取って、以下のコマンドを実行します。

xargs -I KEY aws s3api put-object-acl --bucket target-bucket --key "KEY" --acl bucket-owner-full-control

xargsコマンドは、標準入力からインプットを受けてコマンドを実行するものです。

-Iオプションに指定した変数(今回の例ではKEY)を置き換え文字とし、標準入力から受け取ったオブジェクトキー名を後続コマンドaws s3api put-object-acl--keyオプションに当てています。


以上この3段階のコマンドを経て、指定したディレクトリ以下にある全オブジェクトに--acl bucket-owner-full-controlを付与さることができます。


旧バージョンコマンドの解説

aws s3 ls s3://target-bucket/ --recursive | awk '{print $4}' | xargs -I KEY aws s3api put-object-acl --bucket target-bucket --key "KEY" --acl bucket-owner-full-control

こちら旧バージョンコマンドの解説も残しておきます。

前述の通り、こちらはオブジェクトキーに日本語が入っていたり、スペースが入っていたりすると上手く機能しないので注意が必要です。

aws s3 ls s3://target-bucket/ --recursive

まずはこのaws s3 lsコマンドで、指定したS3バケット/ディレクトリ以下にある全オブジェクトを取得します。

このコマンド単体の実行結果は以下のようになります。

$ aws s3 ls s3://target-bucket-001/ --recursive
2020-11-02 12:45:17          3 aaa.txt
2020-11-02 12:45:17         12 bbb.txt
2020-11-02 12:45:17          3 ccc.txt
2020-11-02 12:45:17          3 ddd.txt
2020-11-02 12:45:17         12 eee.txt
2020-11-02 12:45:17          3 fff.txt


次に、上記実行結果がawkコマンドに渡されます。

awk '{print $4}'

awkコマンドは、テキストデータをパターンで処理できるコマンドです。 '{print $4}'を指定することで、4行目を出力させています。

ここまでを合わせると、出力は以下のようになります。

$ aws s3 ls s3://target-bucket-001/ --recursive | awk '{print $4}'
aaa.txt
bbb.txt
ccc.txt
ddd.txt
eee.txt
fff.txt

ちょうどオブジェクトキーが出力される形になります。


最後にこの出力を受け取って、以下のコマンドを実行します。

xargs -I KEY aws s3api put-object-acl --bucket target-bucket --key "KEY" --acl bucket-owner-full-control

xargsコマンドは、標準入力からインプットを受けてコマンドを実行するものです。

-Iオプションに指定した変数(今回の例ではKEY)を置き換え文字とし、標準入力から受け取ったオブジェクトキー名を後続コマンドaws s3api put-object-acl--keyオプションに当てています。


以上この3段階のコマンドを経て、指定したディレクトリ以下にある全オブジェクトに--acl bucket-owner-full-controlを付与さることができます。


おわりに

S3バケットの既存オブジェクトに、--acl bucket-owner-full-controlを一括付与するやり方の備忘録を書きました。

今回はbucket-owner-full-controlを取り上げましたが、ほかのACL権限設定についても同様のやり方で対処することが出来ます。

また、もちろんBoto3などSDKを用いても同様の処理を書くことができます。

が、一行で済んでしまうこの手軽さは、コマンド良いところだと改めて感じます。


関連記事

S3バケットポリシーとIAMポリシーの関係を、同一アカウント・クロスアカウントそれぞれにおいて整理しました。 www.bioerrorlog.work


AWS CLIのs3 cps3 syncの違いをまとめました。 www.bioerrorlog.work


Boto3でAssumeRoleするやり方を書きました。 www.bioerrorlog.work


参考

Resolve 403 errors from S3 objects uploaded by other accounts

Require access to S3 objects uploaded from another AWS account

Bucket policy examples - Amazon Simple Storage Service

Amazon S3 Object Ownership is available to enable bucket owners to automatically assume ownership of objects uploaded to their buckets

Controlling ownership of uploaded objects using S3 Object Ownership - Amazon Simple Storage Service

grepコマンドで特定の文字列を含むファイルを検索する | Linux shell

ある特定の文字列を含むファイルをLinuxコマンドで検索する方法を整理します。

はじめに

こんにちは、@bioerrorlogです。

コードを検索したいときなど、特定の文字列を含むファイルをコマンドで検索したい時があります。

そのたびに毎回コマンド調べているので、今回はそのやり方の備忘録を残します。

ある文字列を含むファイルをコマンドで検索する

やり方

特定の文字列をあるディレクトリ以下で再帰的に検索するには、以下のコマンドを使います:

grep -r [検索する文字列] [検索対象のパス]


使用例:
以下の例ではfuncという文字列を、./srcディレクトリ以下で再帰的に検索します。

$ grep -r "func" ./src
./src/Main.gd:func _ready():
./src/Main.gd:func _process(delta):
./src/Prey.gd:func _physics_process(delta):
./src/Boid.gd:func _ready():
./src/Boid.gd:func _process(delta):
./src/Boid.gd:func set_prey_position(position: Vector2):
./src/Boid.gd:func process_centralization(centor: Vector2):
./src/Boid.gd:func process_cohesion(neighbors):
./src/Boid.gd:func process_alignments(neighbors):
./src/Boid.gd:func process_seperation(neighbors):
./src/Boid.gd:func steer(var target):
./src/Boid.gd:func get_neighbors(view_radius):


また、出力結果をファイル名のみにする場合は、オプションに-lを追加します:

grep -rl [検索する文字列] [検索対象のパス]


使用例:
以下の例ではfuncという文字列を./srcディレクトリ以下で再帰的に検索し、該当のファイル名を出力します。

$ grep -rl "func" ./src
./src/Main.gd
./src/Prey.gd
./src/Boid.gd


解説

それでは、上で紹介したコマンドを一つずつ解説します。

まずgrepは、与えたパターンをファイルから検索するコマンドです。

$ man grep
DESCRIPTION
   grep  searches  for  PATTERN  in  each  FILE.


grepコマンドは、以下の基本文法で使用します:

SYNOPSIS
grep [OPTION...] PATTERNS [FILE...]


上の使用例をこれに当てはめますと:

$ grep -rl "func" ./src

-rlというオプションで、funcというパターンを./srcパスで検索している、ということになります。


ここで-rlは、-rオプションと-lオプションを併用していることを意味しています。

-rオプションは、指定したパス以下を再帰的(recursively)に検索することを指定します。

-lオプションは、出力をファイル名のみに絞ることを指定します。

$ man grep

-r, --recursive
        Read all files  under  each  directory,  recursively,  following
        symbolic  links only if they are on the command line.  Note that
        if  no  file  operand  is  given,  grep  searches  the   working
        directory.  This is equivalent to the -d recurse option.

-l, --files-with-matches
        Suppress normal output; instead print the  name  of  each  input
        file  from  which  output would normally have been printed.  The
        scanning will stop on the first match.


補足: 特定ディレクトリをgrep対象から除外する

.gitディレクトリや.terraformディレクトリなど、容量は大きいけどgrepしなくてよいディレクトリを検索対象から除外したいことがあります。

特定ディレクトリをgrep対象から除外するには、--exclude-dirオプションを使用します。

grep -r "events" . --exclude-dir={.git,.terraform}

--exclude-dir={.git,.terraform}のように、{}内でコンマ区切りに指定することで複数ディレクトリを排除指定できます。

おわりに

今回は、ある文字列を含むファイルをLinuxコマンドで検索する方法を簡単にメモしました。

ちょっとした(しかし面倒くさい)こういった処理をパッとできてしまうのは、コマンド処理のいいところだなと改めて感じます。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

参考

grep(1) — Arch manual pages

How to use the grep command in Linux - Web24

How to Grep for Text in Files | Linode

【find・grep】特定の文字列を含むファイルのリストを取得する方法。 - Qiita

エラー対処: RuntimeError: Click will abort further execution because Python 3 was configured to use ASCII as encoding for the environment.

以下のエラーの対処法を記します。

RuntimeError: Click will abort further execution because Python 3 was configured to use ASCII as encoding for the environment. 
Consult https://click.palletsprojects.com/python3/ for mitigation steps.


はじめに

おはよう。@bioerrorlogです。

先日、ある作業をしているときに、次のエラーに遭遇しました。

RuntimeError: Click will abort further execution because Python 3 was configured to use ASCII as encoding for the environment. 
Consult https://click.palletsprojects.com/python3/ for mitigation steps.

This system supports the C.UTF-8 locale which is recommended. 
You might be able to resolve your issue by exporting the following environment variables:

    export LC_ALL=C.UTF-8
    export LANG=C.UTF-8

ClickというPythonパッケージ*1のロケールについてのエラーのようです。

エラーメッセージには既に解決策が示されていますが、私の場合はそれでは解決せず、長い間右往左往してました。

今回は、このエラーの解決方法を書き残します。


作業環境

作業はUbuntu上のCloud9で行い、Pythonバージョンは以下の通りでした。

$ lsb_release -d
Description:    Ubuntu 18.04.4 LTS

$ python --version
Python 3.6.9


エラー対処

解決策1: export LC_ALL=C.UTF-8

まず最初に行うべき対処は、エラーメッセージに従い、以下のようにロケールを変更することです。

export LC_ALL=C.UTF-8
export LANG=C.UTF-8

エラーメッセージで検索した時にでヒットするstack overflowでも専らこの解決策が議論されており、多くの状況でこの対処法が機能するようです。

なお、システムによってはUTF-8の表記に多少の差異があるようで、場合によっては次のようにUTF8と記述する必要があるようです。

export LC_ALL=C.UTF8
export LANG=C.UTF8


なお、どのようなロケール表記がサポートされているかは、次のコマンドで確認できます。

locale -a


しかし、私の場合は上記のいずれの対処法でも解決しませんでした。


解決策2: Python3.7以上を使う

そこで次の解決策は、Python3.7以上を使うことです。

エラーメッセージにも示されているClickのドキュメントページには、以下の記載があります。

In Python 3.7 and later you will no longer get a RuntimeError in many cases thanks to PEP 538 and PEP 540, which changed the default assumption in unconfigured environments.

Python3.7以上ではRuntimeErrorは起きないよ、とのことです。

私の場合はまさしく、Python3.7をインストールすることでエラーが解消しました。

Python3.7のインストール + Python3.7による仮想環境の構築は、以下のようにして実行します。

# Python3.7 インストール
sudo apt update
sudo apt install python3.7

# python3.7-venvのインストール
sudo apt install python3.7-venv

# Python仮想環境の作成とアクティブ化
python3.7 -m venv .venv
source .venv/bin/activate


以上のように、Python3.7の環境を再構築することで、このエラーを解消することが出来ました。


おわりに

今回は、PythonパッケージClickのロケールエラーの解消方法を記しました。

エラーメッセージに示されている解決法が機能しなかったことで少し焦ってしまい、長い時間を無駄にしてしまいました。

困ったらまずドキュメントをよく読む、という基本の大切さを改めて身体に刻みます。

以上、同じ境遇のどなたかの参考になれば幸いです。


参考

Python 3 Support — Click Documentation (7.x)

*1:もう少し補足すると、Clickは“Command Line Interface Creation Kit”です。

Session Managerでec2-userやrootとして作業する | AWS Systems Manager

AWS Systems Manager(SSM)のSession Manager (以下セッションマネージャー) でec2-userやrootとして作業するやり方の備忘録です。

はじめに

こんにちは、@bioerrorlogです。

SSM セッションマネージャーは、いちいちSSHでログインすることなく、EC2インスタンスでシェル操作を行うことのできる便利なサービスです。

ただ、SSHでec2-userとしてログインした時とは微妙な違いがあります。

今回は、SSM セッションマネージャーでユーザーec2-userやrootユーザーとして作業するやり方を簡単にメモします。

環境

EC2インスタンス: Amazon Linux 2
SSMエージェントのバージョン: 2.3.714.0

Session Managerでec2-userやrootとして作業する

現状: ssm-userとしてシェルアクセス

セッションマネージャーでEC2インスタンスに入ると、ssm-userとしてシェルアクセスされます。

$ whoami
ssm-user

しかし、ssm-userのままだと、EC2にデフォルトで作成されるユーザーec2-userのファイルにアクセスできません。

# ssm-userのホームディレクトリへ行く
$ cd ~

# ec2-userのホームディレクトリにアクセスする
$ cd ..
$ ls
ec2-user  ssm-user
$ cd ec2-user
sh: cd: ec2-user: Permission denied

ここでssm-userのままec2-userのファイルにアクセスしようと思えば、sudoを使うことになるでしょう。

しかし、毎回sudoを使うのは面倒です。

解決策: sudo su --login ec2-user

気付いてしまえばあまりに簡単なことなのですが、sudoの権限を用いてec2-userにログインしてしまえば、ec2-userとしてSSHした時に近い感覚で作業が出来ます。

# ec2-userにログイン
$ sudo su --login ec2-user
Last login: Thu Mar 12 13:44:03 UTC 2020 on pts/0

# ec2-userに切り替わったことを確認
$ whoami
ec2-user


同様に、以下のようにしてrootユーザーに切り替えることもできます。

# rootにログイン
$ sudo su --login
Last login: Thu Mar 12 13:43:50 UTC 2020 on pts/0

# rootに切り替わったことを確認
$ whoami
root

おわりに

sudo権限を用いてユーザーを切り替えればよい、というのはあまりに単純な話なのですが、私はそれに気付かないばかりに、セッションマネージャー少し使いづらいなと思っていました。

同じように思った方の参考になれば幸いです。

[関連記事]

www.bioerrorlog.work

www.bioerrorlog.work

VMware上のUbuntuをマルチディスプレイにする

VMware上で起動しているUbuntuを、マルチディスプレイで使用する方法を記録します。


はじめに

おはよう。@bioerrorlogです。

現在、Ubuntu18.04.1 LTS をWindows10の上にVMware Workstation Playerによって構築した仮想環境で使用しています。

www.bioerrorlog.work

これまでは一つのモニタを使ってましたが、マルチディスプレイで作業したくなりました。

今回は、VMware上のUbuntuをマルチディスプレイ(デュアルディスプレイ)に設定する方法を記録します。


VMware上のUbuntuをマルチディスプレイにする

最終目的: "複数のモニタを循環" をONにすること

"複数のモニタを循環"をONにすれば、マルチディスプレイを使用することができます。

"複数のモニタを循環"のボタンは、以下の2つの場所にあります。

  • VMwareツールバー > "複数のモニタを循環"マーク
  • VMwareツールバー > Player(P) > 複数のモニタをサイクル(C)

※前提として、フルスクリーンモードにしてある必要があります。

しかし、いきなりこれを押すと次のようなエラーを吐かれてしまいます。

-仮想マシンに最新のVMware Toolsがインストールされて、
稼働している必要があります。

そこでまず、VMware Toolsのインストールを試みました。


VMware Toolsと言われるものには、2つのものがあります。

  • VMware側が配布している"VMware Tools"
  • OS(Ubuntu)側が配布しているVMware Toolsのオープンソース版"open-vm-tools"

推奨されているのは"open-vm-tools"です。 インストール手順も、圧倒的に"open-vm-tools"のほうが簡単でした。


※私は"VMware Tools"をインストールしようとして、そのインストーラー起動時に"open-vm-tools"を推奨する警告を受け取り、"open-vm-tools"をインストールしたという経緯があります。


そこで、まずは"open-vm-tools"のインストール手順を記録します。


open-vm-toolsのインストール: 推奨

こちらは極めて簡単です。 ただopen-vm-toolsをaptインストールすれば済みます。

$ sudo apt install open-vm-tools


※追記
open-vm-toolsをインストールして再起動しても"複数のモニタを循環"マークが押せない場合は、"open-vm-tools-desktop"をインストールすると上手くいくことがあります。

$ sudo apt install open-vm-tools-desctop

open-vm-tools-desctopは、open-vm-toolsの追加パッケージのようです。
open-vm-toolsのGithubレポジトリに少し記述があります。

NOTE: Most of the Linux distributions ship two open-vm-tools packages, "open-vm-tools" and "open-vm-tools-desktop". "open-vm-tools" is the core package without any dependencies on X libraries and "open-vm-tools-desktop" is an additional package with dependencies on "open-vm-tools" core package and X libraries.

open-vm-toolsはX librariesと依存関係のないコアパッケージ、open-vm-tools-desktopはX librariesと依存関係のある追加パッケージ、とのことです。
(X librariesが何者なのか、少し調べてもよくわかりませんでした。)


VMware Toolsのインストール: 非推奨

つぎに、VMware Toolsのインストール手順の記録を、一応残します。 ただし、VMware Toolsのインストールは手順が面倒な上に、インストール直前にはopen-vm-toolsのインストールを公式に勧められます。 素直にopen-vm-toolsをインストールするべきでしょう。

Perlがインストールされているかを確認する

VMware Toolsのインストールを始める前に、Perlがインストールされているかを確認します。 VMware Tools インストーラが Perl で書かれているためです。 ターミナルでperl -verionを実行して確認しました。

$ perl -version

This is perl 5, version 26, subversion 1 (v5.26.1) built for x86_64-linux-gnu-thread-multi
(with 67 registered patches, see perl -V for more detail)

Copyright 1987-2017, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

こんな感じになっていれば、perlはすでにインストールされています。

もしインストールされていなければ、aptインストールします。

$ sudo apt install perl


VMware Toolsをインストールする

それではVMware Toolsをインストールしていきます。
VMware Toolsは、仮想CD-ROMからインストールする形をとるようです。

VMwareツールバー > Player(P) > 管理(M) > VMware Tools のインストール(T)...

とすると、仮想CD-ROMがマウントされます。

"Files"から確認すると、CDメディアの欄に"VMware Tools"が挿入されているのが確認できます。
あるいはlsコマンドで挿入メディアを確認すると、

$ ls /media/<user name>
'VMware Tools'

"VMware Tools"の挿入が確認できます。


つぎに、この仮想CD-ROMにある圧縮ファイルを解凍し、インストーラを実行します。

解凍する場所は、/tmpディレクトリとしました。 /tmpディレクトリは、一定期間後に中のファイルが自動的に削除される一時的な作業ディレクトリです。

/tmpディレクトリに移動し、仮想CD-ROMの圧縮ファイル(VMwareTools-10.3.2-9925305.tar.gzのようなもの)を解凍します。

$ cd /tmp
$ tar -zxpf '/media/<user name>/VMware Tools/VMwareTools-10.3.2-9925305.tar.gz'

これで、解凍フォルダ"vmware-tools-distrib"が作成されました。

つぎに、この"vmware-tools-distrib"フォルダの中にあるインストーラ"vmware-install.pl"を、管理者権限sudoで実行します。

$ sudo ./vmware-install.pl
[sudo] password for <user name>: 
open-vm-tools packages are available from the OS vendor and VMware recommends 
using open-vm-tools packages. See http://kb.vmware.com/kb/2073803 for more 
information.
Do you still want to proceed with this installation? [no] 

するとこのように、公式にopen-vm-toolsのインストールを勧められます。 なので私は、open-vm-toolsを上記のようにしてインストールしました。


"複数のモニタを循環" をONにする

VMware Tools(open-vm-tools)のインストールが完了したので、"複数のモニタを循環" をONにします。

  • VMwareツールバー > "複数のモニタを循環" をクリック

遂にこれで、マルチディスプレイが使用できるようになりました。


おわりに

今回は、VMware上のUbuntuをマルチディスプレイで使用する方法を記録しました。

蓋を開けてみればopen-vm-toolsの簡単なインストールだけで済む話でした。

が、VMwareドキュメントを参考に作業したおかげで、open-vm-toolsの存在を知らないまま面倒なVMware Toolsのインストール手順を進めてしまいました。

私と同じ道を歩む人が少しでも減るよう願います。


関連記事

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work


参考

1 つの仮想マシンでの複数モニタの使用

Linux 仮想マシンへの VMware Tools の手動インストール