Quantcast
Channel: mattintosh note
Viewing all 880 articles
Browse latest View live

Majaro Linux を使い始める

$
0
0

先日、研修講師をやってたときに使ったノート PC を初期化することにした。今日の DistroWatch のランキングでは MX Linuxが 1 位だったけどちょっとデザインがイマイチかな。というかもう KDEになれすぎて GNOME系は物足りない。Kubuntuにも少し飽きてきたのでまた Arch を使うことにして Manjaro をチョイス。メモリ消費量は Firefoxを起動して 1 GB 前後。Yakuake が標準で入ってて助かる。

f:id:mattintosh4:20190523232728p:plain
Manjaro Linux

日本語入力設定

私の基本的なロケールen_US.UTF-8で、文字入力だけ日本語です。

以下のパッケージをインストールしておきます。KDEだが GTK系も入れておかないと FirefoxGoogle ChromeChromiumといったアプリケーションで日本語が入力できない。

  • fcitx
  • fcitx-gtk2
  • fcitx-gtk3
  • fcitx-mozc
  • fcitx-qt5
  • kcm-fcitx
sudo pacman -S fcitx fcitx-mozc fcitx-gtk2 fcitx-gtk3 fcitx-qt5 kcm-fcitx

インプットメソッドの設定で Mozc を追加しておく。左欄に英語しか出てこない場合や Mozc が出てこない場合は下にあるチェックボタンを外すと出てくるはず。

f:id:mattintosh4:20190523234018p:plain
Input Method

~/.xprofileに下記のように書いておく。デスクトップ環境にログインしたときに自動的に読み込まれる。この設定がないと fcitx はウィンドウを補足できない。/etc/environmentに記述しておく方法もあるがこちらの方がユーザごとに任意に設定ができる。

export XMODIFIERS=@im=fcitx
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx

一旦ログアウトするか再起動して Kate などの KDEアプリケーション、Firefoxなどの GTKアプリケーションで日本語が入力できれば OK。ウィンドウを切り替えたときに画面端のキーボードアイコンが Mozc のアイコンに変わらない場合は ~/.xprofileのスペルミスなどが考えられる。fcitx-diagnose環境変数が正しく設定されているか確認するとよい。


fcitx の設定なんてしょっちゅうやるものではないので軽くネットを徘徊したときに見つけたけど下の二つは設定方法が間違ってますね。(片方は Manjaro 公式 Wikiっぽいのでちゃんとして欲しいというか本家の Arch Wikiがあんなに丁寧に書いてるのになぜここで間違ったことを書くのか…)


さてメモリ 4 GB しかないけど何しようかな…(´・ω・`)


macOS で Xcode の要らない SDK を消して空き領域を増やす

$
0
0

Xcode使ってますか?最近は Command Line Tools なんてものがあるので Xcode.app をわざわざ入れる必要がなくなりましたよね(最近って言うほど最近ではない)。私は人様に配布するものを作っているので Xcode.app のお世話になっています。

この Xcode.app ですが、インストールすると約 5 GB くらいになります。32-bit のコンパイルもするので xcode-selectXcode 9.x 系と Xcode 10.x 系を切り替えて使うんですが、両方合わせると 10 GB を超えます。

Xcode.app には様々なプラットフォームに応じたツールが入っています。以下は 9.2 の場合です。

  • AppleTVOS.platform
  • AppleTVSimulator.platform
  • MacOSX.platform
  • WatchOS.platform
  • WatchSimulator.platform
  • iPhoneOS.platform
  • iPhoneSimulator.platform

この中で私が使うのは MacOSXだけです。なので要らないプラットフォームは毎回削除してます。(xipコマンドに exclude 的なオプションがありそうな気もするがマニュアルには解凍の -xオプションすら載っていない)

まずは MacOSX.platform以外のプラットフォームディレクトリを探します。

Terminal

find /Applications/Xcode.app -type d -name "*.platform" \! -name "MacOSX.platform"

出てくるのものは下記の通りですが、私は AppleTV も iPhoneも AppleWatch も開発しませんので消します。

/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform
/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVSimulator.platform
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform
/Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform
/Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/Developer/Platforms/AppleTVSimulator.platform
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/Developer/Platforms/iPhoneSimulator.platform

削除前の容量を確認しておくと Xcode 9.2 で 5.7 GB でした。

Terminal

$ du -sh /Applications/Xcode.app
5.7G    /Applications/Xcode.app

Terminal

find /Applications/Xcode.app -type d -name "*.platform" \! -name "MacOSX.platform" | sudo xargs rm -rf

削除前は 5.7 GB でしたが 1.4 GB まで減りました。かなりの減量ですね。

Terminal

$ du -sh /Applications/Xcode.app
1.4G    /Applications/Xcode.app

xcodebuildコマンドで SDKを確認すると macOSSDKしか出てこなくなります。

Terminal

$ xcodebuild -showsdks
macOS SDKs:
        macOS 10.13                     -sdk macosx10.13

「メインでは Xcode 10.x 系を使っているんだけどたまに Xcode 9.x 系使いたいんだよなぁ…」という時に 9.x 系の不要な SDKを削除しておくと容量を無駄に喰わなくて済みます。

Cisco Packet Tracer 用 Docker コンテナを作る

$
0
0

タイトルの通り。Cisco Packet Tracer が Ubuntu 14.04 向けなら Ubuntu 14.04 で環境を作ればいいじゃない!」というノリ。

「ん?X11転送以外で Docker コンテナから GUIウィンドウってホストに持ってこれるのか?」と思ったけど -v /tmp/.X11-unix/X0:/tmp/.X11-unix/X0でソケット共有したら普通に使えた。

-v $HOME/pt:/home/cisco/ptとかでホストのディレクトリをマウントしておかないとファイルを作成してもコンテナから取り出せなくなる。

git clone https://gist.github.com/4a18b03d22d1206e55bdfcc73ebc7172.git docker-packettracer
cd docker-packettracer
cp ~/Downloads/Packet\ Tracer\ 7.1.1\ for\ Linux\ 64\ bit.tar.gz .
docker build -t packettracer .
docker run -v /tmp/.X11-unix/X0:/tmp/.X11-unix/X0 -v$HOME/pt:/home/cisco/pt --name packettracer packettracer

一度コンテナを作ったあとは docker startだけでよい。

docker start packettracer

macOS での Wine の日本語設定(2019年版)

$
0
0

昔書いた記事が古くなったので改めてまとめておきます。

Homebrew の Wine は依存関係に gettext が入っていないためメニューの「ファイル」や「編集」などの部分が日本語にならないことがあります。これは翻訳データの中にそもそも日本語が入っていないのでレジストリの設定ではどうすることもできません。gettext をインストールした状態で Wine を再インストールすれば有効になる可能性はありますがバイナリ形式でインストールされる場合はどうしようもありません。Mojave の Homebrew では恐らくボトルというバイナリ形式でインストールされています。解決策が無いわけではありませんが長くなるのでここには書きません。

なお、一部が英語になる可能性はありますが Windows アプリケーション内の日本語の部分は問題ないはずです。

さくっと設定したい人

これが一番手っ取り早い方法です。下記のコードを最後の改行までしっかりコピーして Terminal.app に貼り付ければ完了です。お疲れさまでした。

Terminal

iconv -f UTF-8-t CP932 <<! | LANG=ja_JP.UTF-8 wine regedit -REGEDIT4[HKEY_CURRENT_USER\\Control Panel\\Desktop]"FontSmoothingType"=dword:00000002[HKEY_CURRENT_USER\\Software\\Wine\\Fonts\\Replacements]"MS UI Gothic"="ヒラギノ丸ゴ ProN W4""MS ゴシック"="ヒラギノ丸ゴ ProN W4""MS Pゴシック"="ヒラギノ丸ゴ ProN W4""MS 明朝"="ヒラギノ明朝 ProN W3""MS P明朝"="ヒラギノ明朝 ProN W3"!

FontSmoothingType の違いについては下記の画像を参考にしてください。

f:id:mattintosh4:20190527224730p:plain
"FontSmoothingType"=dword:00000001

f:id:mattintosh4:20190527224822p:plain
"FontSmoothingType"=dword:0000002

以下は Wine に興味がある方のみ引き続きお読みください。


日本語を含むレジストリデータを regedit.exe に渡す場合、以下のことを守る必要があります。例えば REGEDIT4が書いてない場合、regedit.exe はデータを読み込みません。また、文字コードを CP932 にしていても Wine が LANG=ja_JP.UTF-8以外(例えば LANG=en_US.UTF-8)で実行されると正しくデータが登録されません。

実際の Windows 10 のレジストリエディタを確認しましたが、REGEDIT4Windows Registry Editor Version 5.00に変わり、文字コードも UTF-16LE のようでした。この方法が Wine の方で使えるかはいまのところ確認していません。

system.reg や user.reg を直接編集したい人

system.reg や user.reg(以下、user.reg としてまとめて説明します)はアスキーテキストになっているので文字列型値(REG_SZ)に直接日本語を書くことができません。例えばレジストリエディタで HKEY_CURRENT_USER\Software\Wine\Fonts\Replacementsというキーに文字列値として名前が「MS UI Gothic」でデータが「ヒラギノ丸ゴ ProN W4」という設定をしたとします。

f:id:mattintosh4:20190527211837p:plain
Wine - Registry Editor

この場合、user.regには下記のように登録されます。

user.reg

[Software\\Wine\\Fonts\\Replacements]
"MS UI Gothic"="\x30d2\x30e9\x30ae\x30ce\x4e38\x30b4 ProN W4"

Wine のフォント設定を紹介しているサイトでは「この文字をコピーして貼り付けてください」と説明しているのを見かけますがこれだとアレンジが効かないんですよね。そもそもエスケープされた文字の元がなんだったのかもわからないので不安です。ここではちゃんと自分で日本語から設定を作成して user.reg の形式に合うように変換する方法を紹介します。

まず、テキストエディタで設定を作ります。user.reg の書式は下記のようになっています。ダブルクォートなどの規則をしっかり守りましょう。

"名前"="データ"

私がよく使う HKEY_CURRENT_USER\Software\Wine\Fonts\Replacementsに設定するスタンダードな設定は下記の通りです。

レジストリ.reg

"MS UI Gothic"="ヒラギノ丸ゴ ProN W4""MS ゴシック"="ヒラギノ丸ゴ ProN W4""MS Pゴシック"="ヒラギノ丸ゴ ProN W4""MS 明朝"="ヒラギノ明朝 ProN W3""MS P明朝"="ヒラギノ明朝 ProN W3"

これを iconvに通しますが、--unicode-substオプションを使って \xhhhhで出力されるようにします。

Terminal

/usr/bin/iconv -f UTF-8--unicode-subst="\x%04x"-t ISO-8859-1レジストリ.reg

Result

"MS UI Gothic"="\x30d2\x30e9\x30ae\x30ce\x4e38\x30b4 ProN W4"
"\xff2d\xff33 \x30b4\x30b7\x30c3\x30af"="\x30d2\x30e9\x30ae\x30ce\x4e38\x30b4 ProN W4"
"\xff2d\xff33 \xff30\x30b4\x30b7\x30c3\x30af"="\x30d2\x30e9\x30ae\x30ce\x4e38\x30b4 ProN W4"
"\xff2d\xff33 \x660e\x671d"="\x30d2\x30e9\x30ae\x30ce\x660e\x671d ProN W3"
"\xff2d\xff33 \xff30\x660e\x671d"="\x30d2\x30e9\x30ae\x30ce\x660e\x671d ProN W3"

あとはコピーして貼ればいいんじゃないかな。

(余談)Linuxの場合

Linuxiconvには macOSのような --unicode-substオプションは無いが、uconv--to-callback escape-cを使えば \uhhhh形式で出てくるのでこれを sedで変換する。

Terminal

uconv -f UTF-8--to-callback escape-c -t ISO-8859-1<<! | sed 's/\u/\x/g'"MS UI Gothic"="VL Pゴシック""MS ゴシック"="VL ゴシック""MS Pゴシック"="VL Pゴシック"!

16進数部は大文字でも小文字でも user.regは気にしなくてよい。

"MS UI Gothic"="VL P\x30B4\x30B7\x30C3\x30AF"
"\xFF2D\xFF33 \x30B4\x30B7\x30C3\x30AF"="VL \x30B4\x30B7\x30C3\x30AF"
"\xFF2D\xFF33 \xFF30\x30B4\x30B7\x30C3\x30AF"="VL P\x30B4\x30B7\x30C3\x30AF"

rundll32.exe に INF を渡して登録する

面倒過ぎるのであまりおすすめしません。下記のファイルに説明が書いてあります。

https://github.com/mattintosh4/osx-wine-inf/blob/master/osx-wine.inf

FontSmoothingType の違い

ローカルとかプライベートネットワークでもういい加減 ssh-keygen -R したくない

$
0
0

最近は仮想環境を使ったり、おうちに Raspberry Piをたくさん設置して SSHで作業することも多くなりましたよね。

SSHで接続先が増えた時に困るのがフィンガープリントの問題です。例えば VirtualBoxでゲスト OS に NAT 経由で localhost:22222 で接続出来るようにしたりしますが、ゲスト OS を入れ直すと ssh-keygen -Rをしなきゃいけないんですね。Raspberry Piraspberrypi.localで接続しますが、まぁ microSDをよく初期化するのでその度に ssh-keygen -Rを叩かされるわけです。特に面倒なのが AWSで EIP 固定で検証用にインスタンをスガンガン作り直したりとかですね…。

グローバルなところは置いといてローカルでホストが変わったとわかりきってるところに ssh-keygenを叩きたくないので私は ~/.ssh/configにこう書いてますというだけの話です。

~/.ssh/config

Host localhost *.local 192.168.*
    StrictHostKeyChecking no
    UserKnownHostsFile    /dev/null

上記は一例ですがこのように書いておくと、

  • localhost
  • *.local(例えば raspberrypi.localなど)
  • 192.168.*(例えば 192.168.1.11など)

に対してホストのチェック(初めて接続する時に聞かれる yes/no のアレ)を行わなくなります。また、ホスト公開鍵を ~/.ssh/known_hostsではなく /dev/nullに保存します。つまり保存しません。何言ってんだ。

この状態で接続してみましょう。Warning: Permanently added '192.168.1.11' (ECDSA) to the list of known hosts.は毎回出ますが出るだけです。

Terminal

$ ssh -p22222 localhost
Warning: Permanently added '[localhost]:22222' (ECDSA) to the list of known hosts.

ご利用は計画的に…😇

Ubuntu で Atom や Haroopad のフォントが汚い

$
0
0

Haroopad。なかなか良いアプリなんだけど Ubuntu 18.04 で使っているとなぜだかレンダリングがおかしい。うちは KDEだし仕方ないのかなぁ〜なんて思ってて、Atomを使う用事があったので起動したらこいつも汚い。freetypeか pango あたりかな、なんて調べたら同じ症状の人発見。

github.com

どうも libefreetype6 の 2.8.1 がダメっぽい。Atomの方は Atom自体をアップグレードしたら正常になったが、Haroopad は最新版でもダメ。

なので libfreetype6 を 2.8.0 にダウングレードしてバージョン固定。

wget http://ftp.jaist.ac.jp/pub/Linux/ubuntu/pool/main/f/freetype/libfreetype6_2.8-0.2ubuntu2_amd64.deb
wget http://ftp.jaist.ac.jp/pub/Linux/ubuntu/pool/main/f/freetype/libfreetype6_2.8-0.2ubuntu2_i386.deb
sudo dpkg -i libfreetype6_2.8-0.2ubuntu2_amd64.deb
sudo dpkg -i libfreetype6_2.8-0.2ubuntu2_i386.deb
sudo apt-mark hold libfreetype6

macOS 上の Wine で FontSmoothingGamma を検証する

$
0
0

0x3e8 (1000) 〜 0x898 (2200) まで 400 刻みでテスト。なお、初期値の 0x0 は 0x578 (1400) と同じとして扱われる。

等倍

f:id:mattintosh4:20190529112015p:plain
"FontSmoothingGamma"=DWORD:0x000003e8 (1000)

f:id:mattintosh4:20190529111739p:plain
"FontSmoothingGamma"=DWORD:0x00000578 (1400)

f:id:mattintosh4:20190529112703p:plain
"FontSmoothingGamma"=DWORD:0x00000708 (1800)

f:id:mattintosh4:20190529112145p:plain
"FontSmoothingGamma"=DWORD:0x00000898 (2200)

部分拡大

f:id:mattintosh4:20190529112233p:plain
"FontSmoothingGamma"=DWORD:0x000003e8 (1000)

f:id:mattintosh4:20190529112322p:plain
"FontSmoothingGamma"=DWORD:0x00000578 (1400)

f:id:mattintosh4:20190529112845p:plain
"FontSmoothingGamma"=DWORD:0x00000708 (1800)

f:id:mattintosh4:20190529112409p:plain
"FontSmoothingGamma"=DWORD:0x00000898 (2200)

macOS - テキストエディット

f:id:mattintosh4:20190529114144p:plain
macOS - テキストエディット

f:id:mattintosh4:20190529114249p:plain
macOS - テキストエディット

0x4b0 (1200) 相当くらいかな?🤔

FontSmoothingType の部分のソースは 4.0.1 時点では下記の通り。

dlls/gdi32/freetype.c

staticstruct font_gamma_ramp *get_font_gamma_ramp( void )
{
    staticconst WCHAR desktopW[] = { 'C','o','n','t','r','o','l','','P','a','n','e','l','\\',
                                      'D','e','s','k','t','o','p',0 };
    staticconst WCHAR smoothing_gamma[] = { 'F','o','n','t','S','m','o','o','t','h','i','n','g',
                                             'G','a','m','m','a',0 };
    const DWORD gamma_default = 1400;
    struct font_gamma_ramp *ramp;
    DWORD  i, gamma;
    HKEY key;

    ramp = HeapAlloc( GetProcessHeap(), 0, sizeof(*ramp) );
    if ( ramp == NULL) returnNULL;

    gamma = gamma_default;
    if (RegOpenKeyW( HKEY_CURRENT_USER, desktopW, &key ) == ERROR_SUCCESS)
    {
        if (get_key_value( key, smoothing_gamma, &gamma ) || gamma == 0)
            gamma = gamma_default;
        RegCloseKey( key );

        gamma = min( max( gamma, 1000 ), 2200 );
    }

    /* Calibrating the difference between the registry value and the Wine gamma value.       This looks roughly similar to Windows Native with the same registry value.       MS GDI seems to be rasterizing the outline at a different rate than FreeType. */
    gamma = 1000 * gamma / 1400;

    for (i = 0; i < 256; i++)
    {
        ramp->encode[i] = pow( i / 255., 1000. / gamma ) * 255. + .5;
        ramp->decode[i] = pow( i / 255., gamma / 1000. ) * 255. + .5;
    }

    ramp->gamma = gamma;
    TRACE("gamma %d\n", ramp->gamma);

    return ramp;
}

logrotate で複数ファイルの指定

$
0
0

ワイルドカード使えるは知ってるけど複数パス同時指定できるかどうか知らなかったので。単純にスペースとか改行とかで区切ればいいようだ。

/tmp/access.log
/tmp/access_custom.log
/tmp/cache.log
{
    weekly
    compress
    compresscmd /bin/bzip2
    missingok
    rotate 3
    postrotate
    killall -HUP /opt/local/squid/sbin/squid
    endscript
}

logrotateのオプションを確認。

Usage: logrotate [OPTION...] <configfile>
  -d, --debug               Don't do anything, just test (implies -v)
  -f, --force               Force file rotation
  -m, --mail=command        Command to send mail (instead of `/usr/bin/mail')
  -s, --state=statefile     Path of state file
  -v, --verbose             Display messages during rotation
  -l, --log=STRING          Log file or 'syslog' to log to syslog
      --version             Display version information

Help options:
  -?, --help                Show this help message
      --usage               Display brief usage message

-dデバッグオプションを付けてチェック。

logrotate -d -f /etc/logrotate.d/squid

ログを見ると considering logで3つ出てくる。

:
中略
:
rotating pattern: /tmp/access.log
/tmp/access_custom.log
/tmp/cache.log
 weekly (3 rotations)
empty log files are rotated, old logs are removed
considering log /tmp/access.log
Creating new state
  Now: 2019-07-09 15:57
  Last rotated at 2019-07-09 15:00
  log does not need rotating (log has been already rotated)
considering log /tmp/access_custom.log
Creating new state
  Now: 2019-07-09 15:57
  Last rotated at 2019-07-09 15:00
  log does not need rotating (log has been already rotated)
considering log /tmp/cache.log
Creating new state
  Now: 2019-07-09 15:57
  Last rotated at 2019-07-09 15:00
  log does not need rotating (log has been already rotated)

以上


孤独の AWS Cloud9 ハンズオン 〜Cloud9 は SSH 踏み台として使えるのか〜

$
0
0

先日、Amazon本社で AWSスタートアップの説明を聞く機会があった。そこで「最近では踏み台に Cloud9 を使っている方も」という話を聞いたので「本当に踏み台として使えるのか」「Terraform との相性はどうなのか」というのを確認してみた。なお、Cloud9 には新規に EC2 インスタンスを作成するタイプと既存の EC2 インスタンスなどに Cloud9 IDEをインストールして Cloud9 environment として使う SSHタイプもあるが後者については触れない。

AWS Cloud9 とは

AWS Cloud9 はブラウザで使えるクラウド上の IDE。本来は開発目的で利用するものなんだろうが EC2 インスタンスを使っているので普通に踏み台として EC2 を構築するのとあまり変わらない。実際、既存の EC2 インスタンスに Cloud9 IDEをインストールしてそのまま「environment」として使うこともできる。

一般的な SSH接続を中継する方法以外に Cloud9 IDEのターミナルからプライベートネットワークにあるインスタンスSSH接続をするという選択肢がある。AWSマネジメントコンソールにアクセスでき、対象の「environment」でターミナルを使う権限があるユーザであれば SSHクライアントなしでプライベートネットワークに配置されているインスタンスにアクセスができる。ブラウザ上でファイル転送もできるので大抵のことは Cloud9 IDE上でできるだろう。

他にも Cloud9 を使うメリットとしては以下のようなことが考えられる。

  • membership というもので IDEにアクセスできる(=ターミナルを利用できる)ユーザを管理することができる。
  • (Cloud9 IDEからしかアクセス出来ないと思われる)セキュリティグループを自動的に作成してくれる。名前は aws-cloud9-環境名-乱数のような書式。
  • インアクティブな状態が続いた場合の自動シャットダウンを「30 分」「1 時間」「4 時間」「1 日」「1 週間」「なし」から設定することができる。踏み台用のインスタンスのコストを抑えることができる。

「お、これは結構使えるのでは?」と思ったが、試しているうちにデメリットも色々と出てきた。詳しくは後述するが、だいたい以下のような点。

  • Cloud9 用のインスタンスを作成したらサーバに接続するための秘密鍵を保存しておく必要がある。
  • 一般的な SSH接続を中継する踏み台として利用する場合、セキュリティグループの編集が必要になったり、EIP を設定したりする必要がああるが自動化が難しい。

現時点での個人的な感想は「踏み台として『使える』か『使えない』かなら『使える』が、何か中途半端」といった感じ。

では孤独のハンズオンで色々と試していく。

Cloud9 environment の作成

Cloud9 では environment(以下、「Cloud9 environment」とする)と membershipでアクセス制限を行っている。作成した Cloud9 environment の membership に IAM ユーザやロールを read-onlyまたは read-writeのいずれかの権限で追加することによって複数のユーザで Cloud9 environment を共有することができるようになっている。

AWSマネジメントコンソールの Cloud9 メニューでは以下のように environment の種類が分かれている。

Your environmentOwner が自身の ARN で登録されている Cloud9 environment が表示される。AWSマネジメントコンソールから作成した場合は必ずこちらに登録される。
Shared with you対象の Cloud9 environment の membership に自身の ARN が read-onlyまたは read-write権限で登録されている Cloud9 environment が表示される。
Account EnvironmentsAWSアカウントに登録されている Cloud9 environment が表示される。自身が Owner の Cloud9 environment 以外に、Owner でもなく membership でも登録されていない Cloud9 environment も表示される。Terraform や AWSCLIで Owner の ARN を指定しなかった場合はここにのみ表示される。

membership には read-onlyread-write以外に ownerがあり、これは Cloud9 environment 作成時に自動的に作成される membership であり変更はできない。

AWSマネジメントコンソール、Terraform、AWSCLIで Cloud9 environment 作成時の挙動が異なるので以下にまとめておく。

AWSマネジメントコンソールから Cloud9 environment を作成する

「Name」は必須だが「Description」は任意。既に同名の Cloud9 environment が存在する場合は作成できない。(Owner が異なる場合は作成可能)

f:id:mattintosh4:20190714230009p:plain
AWS Cloud9

インスタンスタイプや配置する VPC、サブネットなどを選択する。インスタンスタイプは「Other instance type」を選択すれば好きなものを選ぶことができる。執筆時点ではここの「AmazonLinux」は「AmazonLinux 2」ではない。VPCやサブネットはデフォルトでは「デフォルト VPC」と「デフォルトサブネット」を使うようになっている。実際にはプロジェクト用に作成した VPCとサブネットに配置すると思うが、ここで気をつけなければならないのは Cloud9 environment を配置するサブネットはパブリックサブネットでなければならない。Cloud9 によって自動的に作成されるセキュリティグループを見ればわかるがインバウンドルールに Cloud9 用に予約されたネットワークからの 22 番接続を許可する設定が追加される。Cloud9 environment への接続へはグローバルから行われることになるため NAT ゲートウェイの有無に関わらずプライベートサブネットへ配置すると Cloud9 IDEにアクセスできなくなる。

f:id:mattintosh4:20190714230357p:plain
AWS Cloud9 - Create environment

設定内容を確認して[Create environment]ボタンをクリックする。

f:id:mattintosh4:20190714231315p:plain
AWS Cloud9 - Create environment

Cloud9 用のインスタンス作成が行われて接続画面に移行する。Cloud9 用の AMI から作成されているのでだいたい 60 秒もあれば使えるようになる。

f:id:mattintosh4:20190714231458p:plain
AWS Cloud9 - Cloud9 IDE

インスタンスの状態を確認してみる

f:id:mattintosh4:20190715011314p:plain

Cloud9 で作成される EC2 インスタンスとセキュリティグループは CloudFormation によって作成されているのでまずは CloudFormation のスタックを確認する。スタック名は aws-cloud9-{Cloud9環境名}-{Cloud9環境ID}となっている。Cloud9 environment の ID は Cloud9 IDEの URL か AWSCLIcloud9 list-environmentsで調べることができる。

aws cloudformation describe-stacks \--stack-name aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
{"Stacks": [{"StackId": "arn:aws:cloudformation:ap-northeast-1:000000000000:stack/aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "StackName": "aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "CreationTime": "2019-07-14T14:59:45.535Z",
            "RollbackConfiguration": {},
            "StackStatus": "CREATE_COMPLETE",
            "DisableRollback": false,
            "NotificationARNs": [],
            "Tags": [{"Key": "aws:cloud9:environment",
                    "Value": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                },
                {"Key": "aws:cloud9:owner",
                    "Value": "XXXXXXXXXXXXXXXXXXXXX:john"
                }],
            "EnableTerminationProtection": false}]}

スタックのリソースを確認する。

Terminal

aws cloudformation describe-stack-resources --stack-name aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

ここから EC2 インスタンスの ID とセキュリティグループの ID がわかる。

Result

{"StackResources": [{"StackName": "aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "StackId": "arn:aws:cloudformation:ap-northeast-1:000000000000:stack/aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "LogicalResourceId": "Instance",
            "PhysicalResourceId": "i-xxxxxxxxxxxxxxxxx",
            "ResourceType": "AWS::EC2::Instance",
            "Timestamp": "2019-07-14T15:00:31.775Z",
            "ResourceStatus": "CREATE_COMPLETE"
        },
        {"StackName": "aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "StackId": "arn:aws:cloudformation:ap-northeast-1:000000000000:stack/aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
            "LogicalResourceId": "InstanceSecurityGroup",
            "PhysicalResourceId": "sg-xxxxxxxxxxxxxxxxx",
            "ResourceType": "AWS::EC2::SecurityGroup",
            "Timestamp": "2019-07-14T14:59:55.347Z",
            "ResourceStatus": "CREATE_COMPLETE"
        }]}

セキュリティグループは aws-cloud9-{Cloud9環境名}-{Cloud9環境ID}-InstanceSecurityGroup-{乱数}という名前で作成されているので、GroupNameかタグ値で CloudFormation のスタック名をフィルタリングすればすぐ出てくるだろう。

Terminal

aws ec2 describe-security-groups --filters'Name=group-name,Values=aws-cloud9-foo-*'

セキュリティグループのインバウンドルールには Cloud9 で予約されていると思われるネットワークアドレスが二つ登録されている。

Result

{"SecurityGroups": [{"Description": "Security group for AWS Cloud9 environment aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "GroupName": "aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-InstanceSecurityGroup-XXXXXXXXXXXXX",
            "IpPermissions": [{"FromPort": 22,
                    "IpProtocol": "tcp",
                    "IpRanges": [{"CidrIp": "18.179.48.96/27"
                        },
                        {"CidrIp": "18.179.48.128/27"
                        }],
                    "Ipv6Ranges": [],
                    "PrefixListIds": [],
                    "ToPort": 22,
                    "UserIdGroupPairs": []}],
            "OwnerId": "000000000000",
            "GroupId": "sg-xxxxxxxxxxxxxxxxx",
            "IpPermissionsEgress": [{"IpProtocol": "-1",
                    "IpRanges": [{"CidrIp": "0.0.0.0/0"
                        }],
                    "Ipv6Ranges": [],
                    "PrefixListIds": [],
                    "UserIdGroupPairs": []}],
            "Tags": [{"Key": "aws:cloud9:owner",
                    "Value": "XXXXXXXXXXXXXXXXXXXXX:john"
                },
                {"Key": "aws:cloudformation:stack-name",
                    "Value": "aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                },
                {"Key": "aws:cloud9:environment",
                    "Value": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                },
                {"Key": "aws:cloudformation:logical-id",
                    "Value": "InstanceSecurityGroup"
                },
                {"Key": "aws:cloudformation:stack-id",
                    "Value": "arn:aws:cloudformation:ap-northeast-1:000000000000:stack/aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
                }],
            "VpcId": "vpc-xxxxxxxx"
        }]}

EC2 インスタンスも同様。

Terminal

aws describe-instances --filters'Name=tag-key,Values=Name''Name=tag-value,Values=aws-cloud9-foo-*'

{"Reservations": [{"Groups": [],
            "Instances": [{"AmiLaunchIndex": 0,
                    "ImageId": "ami-0872d0e3184cfc976",
                    "InstanceId": "i-xxxxxxxxxxxxxxxxx",
                    "InstanceType": "t2.micro",
                    "LaunchTime": "2019-07-14T14:59:58.000Z",
                    "Monitoring": {"State": "disabled"
                    },
                    "Placement": {"AvailabilityZone": "ap-northeast-1a",
                        "GroupName": "",
                        "Tenancy": "default"
                    },
                    "PrivateDnsName": "ip-172-31-40-231.ap-northeast-1.compute.internal",
                    "PrivateIpAddress": "172.31.40.231",
                    "ProductCodes": [],
                    "PublicDnsName": "ec2-00-000-000-000.ap-northeast-1.compute.amazonaws.com",
                    "PublicIpAddress": "00.000.000.000",
                    "State": {"Code": 16,
                        "Name": "running"
                    },
                    "StateTransitionReason": "",
                    "SubnetId": "subnet-xxxxxxxx",
                    "VpcId": "vpc-xxxxxxxx",
                    "Architecture": "x86_64",
                    "BlockDeviceMappings": [{"DeviceName": "/dev/xvda",
                            "Ebs": {"AttachTime": "2019-07-14T14:59:59.000Z",
                                "DeleteOnTermination": true,
                                "Status": "attached",
                                "VolumeId": "vol-xxxxxxxxxxxxxxxxx"
                            }}],
                    "ClientToken": "aws-c-Insta-XXXXXXXXXXXX",
                    "EbsOptimized": false,
                    "EnaSupport": true,
                    "Hypervisor": "xen",
                    "NetworkInterfaces": [{"Association": {"IpOwnerId": "amazon",
                                "PublicDnsName": "ec2-00-000-000-000.ap-northeast-1.compute.amazonaws.com",
                                "PublicIp": "00.000.000.000"
                            },
                            "Attachment": {"AttachTime": "2019-07-14T14:59:58.000Z",
                                "AttachmentId": "eni-attach-xxxxxxxxxxxxxxxxx",
                                "DeleteOnTermination": true,
                                "DeviceIndex": 0,
                                "Status": "attached"
                            },
                            "Description": "",
                            "Groups": [{"GroupName": "aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-InstanceSecurityGroup-XXXXXXXXXXXXX",
                                    "GroupId": "sg-xxxxxxxxxxxxxxxxx"
                                }],
                            "Ipv6Addresses": [],
                            "MacAddress": "xx:xx:xx:xx:xx:xx",
                            "NetworkInterfaceId": "eni-xxxxxxxxxxxxxxxxx",
                            "OwnerId": "000000000000",
                            "PrivateDnsName": "ip-172-31-40-231.ap-northeast-1.compute.internal",
                            "PrivateIpAddress": "172.31.40.231",
                            "PrivateIpAddresses": [{"Association": {"IpOwnerId": "amazon",
                                        "PublicDnsName": "ec2-00-000-000-000.ap-northeast-1.compute.amazonaws.com",
                                        "PublicIp": "00.000.000.000"
                                    },
                                    "Primary": true,
                                    "PrivateDnsName": "ip-172-31-40-231.ap-northeast-1.compute.internal",
                                    "PrivateIpAddress": "172.31.40.231"
                                }],
                            "SourceDestCheck": true,
                            "Status": "in-use",
                            "SubnetId": "subnet-xxxxxxxx",
                            "VpcId": "vpc-xxxxxxxx"
                        }],
                    "RootDeviceName": "/dev/xvda",
                    "RootDeviceType": "ebs",
                    "SecurityGroups": [{"GroupName": "aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-InstanceSecurityGroup-XXXXXXXXXXXXX",
                            "GroupId": "sg-xxxxxxxxxxxxxxxxx"
                        }],
                    "SourceDestCheck": true,
                    "Tags": [{"Key": "aws:cloudformation:logical-id",
                            "Value": "Instance"
                        },
                        {"Key": "Name",
                            "Value": "aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                        },
                        {"Key": "aws:cloud9:environment",
                            "Value": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                        },
                        {"Key": "aws:cloudformation:stack-id",
                            "Value": "arn:aws:cloudformation:ap-northeast-1:000000000000:stack/aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
                        },
                        {"Key": "aws:cloud9:owner",
                            "Value": "XXXXXXXXXXXXXXXXXXXXX:john"
                        },
                        {"Key": "aws:cloudformation:stack-name",
                            "Value": "aws-cloud9-foo-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                        }],
                    "VirtualizationType": "hvm",
                    "CpuOptions": {"CoreCount": 1,
                        "ThreadsPerCore": 1}}],
            "OwnerId": "000000000000",
            "RequesterId": "000000000000",
            "ReservationId": "r-xxxxxxxxxxxxxxxxx"
        }]}

いずれもタグに Cloud9 environment の ID が入っているのでフィルタリングはしやすい。

Cloud9 environment の menbership について学ぶ

AWSマネジメントコンソールから Cloud9 environment を作成した場合は現在の IAM ユーザやロールの ARN が Owner として設定されるようになっている。

Terminal

aws cloud9 describe-environments \--environment-id aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Result

{"environments": [{"id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            "name": "AWS Management Console",
            "description": "",
            "type": "ec2",
            "arn": "arn:aws:cloud9:ap-northeast-1:000000000000:environment:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            "ownerArn": "arn:aws:sts::000000000000:assumed-role/OrganizationAccountAccessRole/john"
        }]}

上記の Cloud9 environment の membership がどうなっているか確認してみる。

Terminal

aws cloud9 describe-environment-memberships \--environment-id aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Result

{"memberships": [{"permissions": "owner",
            "userId": "XXXXXXXXXXXXXXXXXXXXX:john",
            "userArn": "arn:aws:sts::000000000000:assumed-role/OrganizationAccountAccessRole/john",
            "environmentId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            "lastAccess": 1562846115.0}]}

membershipsが配列になっていることからもわかるが membership には owner以外に read-onlyread-writeといった権限で複数のユーザを登録することができるようになっている。

Cloud9 environment と membership の関連性

Cloud9 environment の権限には ownerread-onlyread-writeの 3 種類がある。AWSマネジメントコンソールから Cloud9 environment を作成した場合、ownerには現在の IAM ユーザやロールが設定される。ownerは当然のことながら変更や削除などすべての操作を行うことができる。

Cloud9 environment には membership というものがあり、この membership をカスタマイズすることで environment を他のユーザと共有できるようになっている。現状の AWSマネジメントコンソールには membership を操作する画面は無く、Cloud9 IDE内の共有設定で行うようになっている。

f:id:mattintosh4:20190712195322p:plain
AWS Cloud9 IDE

Cloud9 environment を AWSマネジメントコンソール、Terraform、AWSCLIからownerArn を指定せずにそれぞれ作成すると以下のようになる。なお、AWSマネジメントコンソールでは ownerArn の指定方法が無いため Owner には自動的に現在のユーザに設定される。

{"environments": [{"id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            "name": "AWS Management Console",
            "description": "",
            "type": "ec2",
            "arn": "arn:aws:cloud9:ap-northeast-1:000000000000:environment:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            "ownerArn": "arn:aws:sts::000000000000:assumed-role/OrganizationAccountAccessRole/john"
        },
        {"id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
            "name": "Terraform",
            "description": "",
            "type": "ec2",
            "arn": "arn:aws:cloud9:ap-northeast-1:000000000000:environment:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
            "ownerArn": "arn:aws:sts::000000000000:assumed-role/OrganizationAccountAccessRole/1562929437597457834"
        },
        {"id": "cccccccccccccccccccccccccccccccc",
            "name": "AWS CLI",
            "description": "",
            "type": "ec2",
            "arn": "arn:aws:cloud9:ap-northeast-1:000000000000:environment:cccccccccccccccccccccccccccccccc",
            "ownerArn": "arn:aws:sts::000000000000:assumed-role/OrganizationAccountAccessRole/botocore-session-1562929475"
        }]}

それぞれの ownerArnを見てみると Terraform ではナノ秒タイムスタンプ、AWSCLIでは botocore-session-接頭辞にタイムスタンプが自動的に設定されている。これらの違いを AWSマネジメントコンソールで確認してみる。

まずは「Your environments」を見てみると AWSマネジメントコンソールで作成した Cloud9 environment が表示されている。自分で作成したので Permissions は Owner となっている。作成したはずの「Terraform」や「AWSCLI」は無い。

f:id:mattintosh4:20190712202037p:plain
AWS Cloud9

「Shared with you」を飛ばして「Account environments」を見てみる。先程は無かった「Terraform」と「AWSCLI」も表示されている。

f:id:mattintosh4:20190712202423p:plain
AWS Cloud9

ではこの「Terraform」や「AWSCLI」が使えるのかというのを「Open IDE」を押して試してみるがアクセス権が無いと言われる。

f:id:mattintosh4:20190712202938p:plain
AWS Cloud9

IDEを開くことができないので「Terraform」と「AWSCLI」は AWSマネジメントコンソールから共有設定をすることができず、AWSCLIから設定することになる。しかし、AWSCLIのロールはオーナーではない membership への DeleteEnvironmentMembership権限が無いので後述する「membership の削除」で問題が発生することがある。

フローにしてみると下記のようになる。

f:id:mattintosh4:20190713012300p:plain
AWS Cloud9

自身が Cloud9 environment の Owner であれば AWSCLIから追加した membership を Cloud9 IDEから削除することができるが、最も困るのが Terraform で owner_arnを未指定で作成してしまった場合。Owner が Terraform で作成した ARN になっているので自身を read-writeで membership を追加したとしても Cloud9 IDEに共有設定が表示されないので membership 操作が一切できない。

membership の追加、更新、削除

Cloud9 environment の ID を調べ方

作成した Cloud9 environment の ID を控え忘れてしまった場合は AWSマネジメントコンソールで「Open IDE」や「View Details」、「Edit」を開けば URL に ID が含まれているのでそれをコピーしてもいい。

AWSCLIでは list-environmentsサブコマンドで ID の一覧を表示することができるが、この結果を describe-environmentsに渡さないと名前がわからない。

Terminal

aws cloud9 list-environments

Result

{"environmentIds": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
        "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
        "cccccccccccccccccccccccccccccccc"
    ]}

一つずつ調べるのは面倒だが list-environmentsの結果を --queryオプションで整形して describe-environments --environment-idsの引数に渡せば名前付きで一覧を取り出すことができる。

Terminal

aws cloud9 describe-environments \--environment-ids$(aws cloud9 list-environments --query "environmentIds" --output text)\--query"environments[].[id, name]"\--output text

Result

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa        AWS Management Console
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb        Terraform
cccccccccccccccccccccccccccccccc        AWS CLI

membership を追加する

membership の追加には create-environment-membershipサブコマンドを使う。ここでは例として IAM ユーザである aliceread-onlyで追加する。

Terminal

aws cloud9 create-environment-membership \--environment-id aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \--user-arn arn:aws:iam::000000000000:user/alice \--permissions read-only

Result

{"membership": {"permissions": "read-only",
        "userId": "YYYYYYYYYYYYYYYYYYYYY",
        "userArn": "arn:aws:iam::000000000000:user/alice",
        "environmentId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    }}

describe-environment-membershipsで確認すると aliceread-onlyで追加されていることがわかる。

Terminal

aws cloud9 describe-environment-memberships \--environment-id aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Result

{"memberships": [{"permissions": "read-only",
            "userId": "YYYYYYYYYYYYYYYYYYYYY",
            "userArn": "arn:aws:iam::000000000000:user/alice",
            "environmentId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
        },
        {"permissions": "owner",
            "userId": "XXXXXXXXXXXXXXXXXXXXX:john",
            "userArn": "arn:aws:sts::000000000000:assumed-role/OrganizationAccountAccessRole/john",
            "environmentId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            "lastAccess": 1562920538.0}]}

membership を更新する

membership の更新には update-environment-membershipサブコマンドを使う。

ここでは上で追加した aliceの権限を read-onlyから read-writeに変更する。

Terminal

aws cloud9 update-environment-membership \--environment-id aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \--user-arn arn:aws:iam::000000000000:user/alice \--permissions read-write

Result

{"membership": {"permissions": "read-write",
        "userId": "YYYYYYYYYYYYYYYYYYYYY",
        "userArn": "arn:aws:iam::000000000000:user/alice",
        "environmentId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    }}

再び describe-environment-membershipsで確認すると aliceの権限が read-writeに変更されていることがわかる。

Terminal

aws cloud9 describe-environment-memberships \--environment-id aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Result

{"memberships": [{"permissions": "read-write",
            "userId": "YYYYYYYYYYYYYYYYYYYYY",
            "userArn": "arn:aws:iam::000000000000:user/alice",
            "environmentId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
        },
        {"permissions": "owner",
            "userId": "XXXXXXXXXXXXXXXXXXXXX:john",
            "userArn": "arn:aws:sts::000000000000:assumed-role/OrganizationAccountAccessRole/john",
            "environmentId": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
            "lastAccess": 1562920538.0}]}

membership を削除する

membership の削除には delete-environment-membershipサブコマンドを使う。

成功した場合は何も表示されない。

Terminal

aws cloud9 delete-environment-membership \--environment-id aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \--user-arn arn:aws:iam::000000000000:user/alice

AccessDeniedException の例

先に説明したように AWSマネジメントコンソールで Cloud9 environment を作成した場合、AWSCLIからの操作には DeleteEnvironmentMembership権限が無いためエラーになる。

Result

An error occurred (AccessDeniedException) when calling the DeleteEnvironmentMembership operation:
User arn:aws:sts::000000000000:assumed-role/OrganizationAccountAccessRole/botocore-session-1562923366
is not authorized to perform: cloud9:DeleteEnvironmentMembership on resource: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

Cloud9 と Terraform

Terraform v0.12.1

Terraform で Cloud9 を扱う場合は aws_cloud9_environment_ec2リソースを使用する。現状では Cloud9 に関連するリソースはこれしか無い。

aws_cloud9_environment_ec2 を使うときの注意点

Cloud9 envionment の membership の説明に書いたとおり、owner_arnの指定を忘れると membership の操作ができないばかりか Cloud9 IDEに入ることすらできないので(使い方によるが)指定しておいた方が無難。

aws_cloud9_environment_ec2に変更を加えた場合、大抵は destroy される。automatic_stop_time_minutesは modify になりそうだが、これも destroy の対象なので自動シャットダウンの時間を変更したければ Cloud9 IDEから変更する必要がある。

modify になるもの

  • nameを変更する
  • descriptionを変更する

destroy になるもの

  • instance_typeを変更する
  • automatic_stop_time_minutesを設定(never から 30 など)または変更(30 から 60 など)する
  • owner_arnを設定または変更する

Terraform による Cloud9 environment の作成

nameinstance_typeだけ指定すれば Cloud9 environment を作成することができる。

aws_cloud9.tf

resource"aws_cloud9_environment_ec2""foo" {// STEP 1name          = "Terraform"
  instance_type = "t2.micro"
}

Terminal

terraform apply --target aws_cloud9_environment_ec2.foo
terraform state show     aws_cloud9_environment_ec2.foo

owner_arnにはユーザ名としてタイムスタンプが設定される。

# aws_cloud9_environment_ec2.foo: 
resource"aws_cloud9_environment_ec2""foo" {arn           = "arn:aws:cloud9:ap-northeast-1:000000000000:environment:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    id            = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
    instance_type = "t2.micro"
    name          = "foo"
    owner_arn     = "arn:aws:sts::000000000000:assumed-role/OrganizationAccountAccessRole/1562844915108062971"
    type          = "ec2"
}

STEP 2: owner_arn の指定

先程の TF ファイルを変更して owner_arnを追記する。Terraform に限らずだが owner の変更は出来ないため同一名の Cloud9 environment を作成する場合は再構築する必要がある。

aws_cloud9.tf

resource"aws_cloud9_environment_ec2""foo" {// STEP 1name          = "foo"
  instance_type = "t2.micro"
  // STEP 2
  owner_arn     = "arn:aws:sts::000000000000:assumed-role/OrganizationAccountAccessRole/john"
}

Terminal

terraform apply --target aws_cloud9_environment_ec2.foo
terraform state show     aws_cloud9_environment_ec2.foo

terraform state showで確認すると owner_arnが指定したとおりに設定されているのがわかる。

# aws_cloud9_environment_ec2.foo: 
resource"aws_cloud9_environment_ec2""foo" {arn           = "arn:aws:cloud9:ap-northeast-1:000000000000:environment:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
    id            = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
    instance_type = "t2.micro"
    name          = "foo"
    owner_arn     = "arn:aws:sts::000000000000:assumed-role/OrganizationAccountAccessRole/john"
    type          = "ec2"
}

STEP 3: automatic_stop_time_minutes を指定する

Cloud9 ではインアクティブな状態が続いたときに自動的に EC2 インスタンスを停止させることができる機能が用意されている。aws_cloud9_environment_ec2リソースでは automatic_stop_time_minutesという引数(数値型)で指定する。未指定の場合は AWSCLI同様に never(停止しない)となる。destroy が発生するので「時間を変更したいけれど Cloud9 environment は壊したくない」という場合は IDEを開いて「AWS Cloud9 > Pereferences > PROJECT SETTINGS > EC2 Instance」で設定を変更する。なお、AWSマネジメントコンソールからは変更できない。

aws_cloud9.tf

resource"aws_cloud9_environment_ec2""foo" {// STEP 1name                        = "foo"
  instance_type               = "t2.micro"
  // STEP 2
  owner_arn                   = "arn:aws:sts::000000000000:assumed-role/OrganizationAccountAccessRole/john"
  // STEP 3
  automatic_stop_time_minutes = 30}

Terminal

terraform apply --target aws_cloud9_environment_ec2.foo
terraform state show     aws_cloud9_environment_ec2.foo

指定した場合は下記のように属性と値が表示される。Q & A に書いておくが設定によっては IDE上で確認できる値と一致しなくなる。指定しなかった場合は自動的に neverとなり automatic_stop_time_minutes属性は出てこない。

Result

# aws_cloud9_environment_ec2.foo: 
resource"aws_cloud9_environment_ec2""foo" {arn                         = "arn:aws:cloud9:ap-northeast-1:000000000000:environment:cccccccccccccccccccccccccccccccc"
    automatic_stop_time_minutes = 30
    id                          = "cccccccccccccccccccccccccccccccc"
    instance_type               = "t2.nano"
    name                        = "bar"
    owner_arn                   = "arn:aws:sts::000000000000:assumed-role/OrganizationAccountAccessRole/john"
    type                        = "ec2"
}

EIP の設定やセキュリティグループのカスタマイズの自動化はできるのか

Cloud9 envionment には EIP の設定が無いので自動シャットダウンが行われればパブリック IP アドレスは変わってしまうし、セキュリティグループは自動作成以外の選択肢が無いのでインバウンドルールを追加しないと本来の「踏み台」としては使えない。

しかし、Cloud9 で EC2 インスタンスを作成してもステータスには EC2 インスタンスの詳細情報は含まれていない。これは AWSCLIを使っても同じである。EC2 インスタンスやセキュリティグループは CloudFormation によって作成されているので Nameタグには aws-cloud9-環境名-環境IDという書式で名前が設定されている。CloudFormation の aws:cloud9:environmentタグにも Cloud9 environment の ID が入っているのでここからリソースを検索することもできるだろう。しかし、CloudFormation のスタックが Terraform の管理外で作成されているので変数呼び出しができない。

EC2 インスタンスの作成を通常通り行い、そちらで Cloud9 IDEのインストールと EIP やセキュリティグループを設定したあとに Cloud9 に SSHタイプで追加すれば…という方法も思いつくが残念ながらいまのところ Terraform には aws_cloud9_environment_sshというリソースは存在しない。

従って、Cloud9 で EC2 インスタンスを新規に作成する場合は「踏み台」として使うための設定の自動化は簡単ではないと思われる。

Try & Result

Try: owner_arn を指定し忘れたのだが Cloud9 IDEを使いたい

AWSCLIcloud9 create-environment-membershipで使用するユーザを membership に追加すればいい。ただし、Cloud9 IDEに membership の設定が表示されず GUIから membership の編集や削除ができないなどの制限があるので潔く作り直したほうがよい。

Try: automatic_stop_time_minutes に適当な値(たとえば 45 など)を設定するとどうなるか

terraform showでは設定した通りの値が入っているが Cloud9 IDEで確認してみると切り上げられてプリセット値に設定されていた。(45 の場合であれば 1 時間)

Try: automatic_stop_time_minutes に明示的に neverを指定するにはどうするのか

数値型なので automatic_stop_time_minutes = 0と指定すれば neverになる。

まとめ

一般的な「踏み台」として使わずに Cloud9 IDESSHログイン用のスポットとして使う分にはいいと思うが、リモートサーバにログインするための秘密鍵を配置する必要があるなどいくつかの手間は残る。

個人的にはシェルのキーバインドを多用するので Ctrl + W(1単語前を消す)なんて押そうものならタブが落ちてしまうため Cloud9 IDE上のターミナルは少々使いにくかったりする。

ただ、フロントの開発をやっているエンジニアさん相手には Proxy Jump の説明をするのも一苦労だったりするので AWSアカウントだけあれば使えるというのは便利なのかもしれない。

他のプロジェクトが Cloud9 をどのように SSHの踏み台として使っているのかは知らないがベストプラクティス的なものが教えてもらいたいものである。

macOS の Wine で使えるゲームパッドを調べてみた

$
0
0

Wine でゲームパッドゲームコントローラー)使ったことがなかったので東方 Project 作品をプレイするにあたっていくつか購入したり借りたりして試しましたのでまとめておきます。

当然ですが macOS対応を謳っている製品は少ないです。「PlayStation用」とか「Windows用」とだけ書いてあるものが macOSで使えたりもします。しかし、Macもモデルや世代などで結構な種類がありますのですべての機種で同じように使えるかどうかはわかりません。その点をご理解いただいた上でお読みください。

有線(Wired)

Buffalo BSGP810GY

使用可です。個人的にアナログスティックが苦手なので十字キーがメインの方が好きです。東方をプレイするならこれくらいのボタン数の方がいいですね。

ODSeven ODS197 クラシックUSBゲームパッド for RaspberryPi/Windows/Mac

秋葉原千石電商さんで ¥500 で売っているスーパーファミコンゲームパッド。全体的に安っぽく、ベコベコします。十字キーがめちゃめちゃ使いにくいので東方をやるにはあまり向いていません。

www.sengoku.co.jp

ホリパッド3 ミニ

使用可です。アナログスティックも動作します。

【PS3対応】ホリパッド3 ミニ クリアブラック

【PS3対応】ホリパッド3 ミニ クリアブラック

無線(Wireless)

8BITDO Android/iOS/PC対応 Bluetooth&USB接続 ゲームコントローラ FC30 GAMECONTROLLER

Bluetooth対応のファミコン風コントローラー。高いだけあって作りは最高です。秋葉原のあきばお〜さんに行けば多分いつでも買えます(店舗によっては取り扱ってないみたいです)。薄くて小さいので持ち運びも楽なんですが大人の手だとLRボタンを押すのがキツイです。

www.akibaoo.co.jp

SONY DUALSHOCK3

皆さんよくご存知のコントローラーですね。私は PlayStationというかゲーム機自体を所持していないので借りたものですが、macOSでも問題なくペアリング出来ました。ただ、ボタン配置が正規の配置になっているかどうかはわかりません。

HORI ワイヤレスコントローラーライト for PlayStation (R) 4 クリアブラック

使用不可です。初回のペアリングは出来るのですが、すぐに切断され、それ以降も接続出来ないため使用できません。Windowsというか Windows筐体?の Linuxでは普通に充電も出来ますしゲームパッドとしても使用可能です。小さくて持ち運びもしやすいので Linuxノート PC と一緒に持ち出すことがあります。Bluetooth 2台接続もできそうですが1台しか持っていないのでまだ試していません。他、以下のような特殊な謎仕様があるので別記事にでもしようかと思います。

  • 「有線では使えません」と説明書に書いてあるが(Linuxでは)有線でも使える(謎)
  • 有線と無線で繋いだときのボタン数の認識の仕方が違う(謎)
  • 一般的な USB 充電器で充電できない(謎)

まとめ

PlayStationを持っている人ならとりあえずプレステのコントローラーでいいんじゃないでしょうか。ボタン配置がめちゃくちゃなのでゲーム側で設定は必須ですが特に問題ないと思います。

自分は最初に HORI のワイヤレスコントローラーを買ったんですが、Macでは使えなかったので Linux機用に。しかし、Macでもワイヤレスで使えるゲームパッドがどうしても欲しくて 8BITDO のゲームパッドを買う羽目に。高いですが品質はめちゃくちゃいいですし、macOS対応をしっかり謳っているのでよい買い物をしたと思うことにしています。

まぁ東方をやるときは一番使いやすい iBuffalo のスーパーファミコンゲームパッドを使っているのだが…。

ESP-WROOM-02 で IoT 夏休み自由研究

$
0
0

「イベント出るから IoT っぽいこと何かやってよ」と言われたので「何か」をやることにした。

LoRa でやろうかとも思ったけど制限多いし市内にゲートウェイあんま無いから使い物にならんなってことで Wi-Fiにした。

Wi-Fi温度計

ESP-WROOM-02と汎用温度センサー LM61CIZ を使った Wi-Fi温度計。ESP8266 の TOUT は 1 V までしか扱えないので分圧等の対応が必要だけど LM61CIZ は 0 ℃が 600 mV で 1 ℃ ごとに 10 mV 増えるので 1 V になるのは 40 ℃ なので「会場が 40 ℃ を超えなければ問題ない!」ということで手抜きで Vo をそのまま TOUT に突っ込んである。データは MQTT で飛ばして Node-RED で表示。外付けの ADC を使えばいいのだけどこの程度の装置に付けるのはちょっと…。

f:id:mattintosh4:20190729183913p:plain
ESP-WROOM-02Wi-Fi温度計

Wi-Fi土壌湿度計

市販の土壌湿度計もあるけど割高なので自作。回路は土壌の抵抗値をトランジスタで変換するだけなので単純。ただし、ESP-WROOM-02の TOUT が 1 V なのでこれも分圧が必要。土壌の抵抗値は土質だいたい数百オームから数メガオームくらいなので抵抗の分圧だけで測定しようと思うとちょっと難しい(湿っているか乾いているかくらいざっくりしたものならトランジスタも使わなくていいと思う)。

f:id:mattintosh4:20190729184103p:plain
ESP-WROOM-02土壌湿度計

試作品なので縦置き抵抗とワニ口クリップを使う。0 Ω 抵抗は見た目を合わせるだけに使ってる。

f:id:mattintosh4:20190729184222p:plain
ESP-WROOM-02土壌湿度計

以前は金メッキプラグなんかで試していたがどうしても腐食してしまうので今回は 2 mm の鉛筆芯を使うことにした。手持ちには 2H もあるのだけど B の方が抵抗値が少なかったので B を採用。

f:id:mattintosh4:20190729184300p:plain
ESP-WROOM-02土壌湿度計

土がなかったのでメラミンスポンジで実験。

この投稿をInstagramで見る

水分量チェッカー(スポンジ試験

mattintosh4さん(@mattintosh4)がシェアした投稿 -

ちなみに金メッキプラグを使用していたときはヘデラを育てていたのだけどプラグが腐食し始めてからプラグに近い部分の茎から徐々に枯れていったので植物に悪影響を及ぼしていそう。錫は錆にくいみたいだけど錫メッキされたものなら植物に影響を与えずに電極棒として使えるのかなぁ…。

IoT コンセント

手元にソリッドステートリレーが転がっていたので作ってみた。これと水槽用エアポンプ、ペットボトル、ソフトチューブを組み合わせて自動水やりができるようにした。自動水やりと言うとよく汲み上げ式のポンプを使っているのを見るのだけど、エアポンプでタンク内の圧力を高めて押し出す方が多分楽だと思う(霧吹きの原理)。

f:id:mattintosh4:20190729185725p:plain
ESP-WROOM-02 IoT コンセント

中継には PVK ボックスを使った。が、屋外用の大きめのボックスを使った方が 3.3 V の AC アダプターも中に入れておけたのでは…と後悔。コンセントを二系統にしたので SSRが二つになってかなり窮屈になった。

f:id:mattintosh4:20190729184558p:plain
ESP-WROOM-02 IoT コンセント

Node-RED のダッシュボードを FireTV のウェブブラウザから弄って水を出してみる。

この投稿をInstagramで見る

遠隔水やり装置作りました

mattintosh4さん(@mattintosh4)がシェアした投稿 -


という感じでぼくのなつやすみのじゆうけんきゅうはこれで終わり(にしたい)。

ESP-WROOM-02のプルアップ抵抗ってだいたい 10 kΩ を使っている例が多いと思うけど 10 kΩ だとたまに起動しないことがあるんだよな…。一番面倒な PVK ボックス内の ESP-WROOM-02が突然起動しなくなったので EN のプルアップ抵抗を 1 kΩに変えたら動くようになった。今後は 4.7 kΩ くらいを使おうかな…。

第六回博麗神社秋季例大祭とコミックマーケット97に申し込みました

$
0
0

タイトルの通りです。令和になって何を血迷ったか同人イベントにサークルとして申し込みました(画力無いのに)。これまで同人イベントには度々行っていたんですが、一般参加じゃなくてサークルとして参加してみたいなと思ったわけです(画力無いのに)。

仕事柄どうしても技術書系の内容くらいしか書けず、それをどう東方Projectと結びつけようかと悩んだ挙句、macOSユーザ向けの東方ゲーム解説本のようなナニカになります。キャラは自分の一番好きな魔理沙を描こうと思っています。「○畜ちゃん」っぽい感じになる…かも。

同人イベントに申し込む時って「本の概要」を書いて送らなくてはいけないんですが、かなり支離滅裂な内容で出したと思います。今頃きっと運営様の方で「何かヤバイの来た」と思われてるかもしれません。

それ以外にも不安が多々あります。

例大祭で技術系の本を出しているサークルはあるの?場違いじゃないの?

多分無いと…思います。夏の例大祭で一応すべての配置を周って「その他」も見てきたのですが技術書的なものを頒布されているサークルは無かったような気がします。この時点で場違いではないかという不安しかない。

そして「ただ自分の書いた本に東方のキャラをいいように使ってるだけじゃない?」みたいな感じになってしまいそうなのがすごく怖い。(そうならないようにちゃんと漫画は描きたい…画力ないけど)

Windowsゲームを macOSで動かそうとする"悪魔の書"みたいなもの出して大丈夫?

Wine を使って macOSでも東方ゲームをやってる人って結構いるだろうし、やりたいと思っている人もいると思ってます。そんな人たちの役に立てれば…と考えたのですがこれもやっぱり不安。そもそも Wine で動かそうとする行為が自己責任であり、そのような行為を拡散させるような書物を総本山の目の前で頒布していいのだろうか…。

動作する保証が無いため EasyWine などの頒布ページにも「製作者様への問い合わせ等はご遠慮ください」と記載はしていますが、これもやっぱり不安。

EasyWine とかの説明書が欲しいと思っている方には申し訳ないですが EasyWine 普及用の同人誌ではないので EasyWine や Nihonshu のことについては掲載しません。

そんな語彙力で大丈夫?

あっ…(察し


という感じで今になって「何故申し込んだし」と思っているのですが、原稿の方はなんとか進めています。しかし、ここでも問題が。

現在の私はフル Linux環境で生きている人間なので IllustratorInDesignなんてものは当然使えず、本を作る環境を作るのに苦労しています。PDF なら何とでもなるんですが、印刷所に入稿するデータを作るとなるとフォントサイズやレイアウト、ページデザイン、断ち切りのサイズ等を考慮しなくてはなりません。Linuxはこの辺が圧倒的に不利だと感じています。

Inkscapeは複数ページを扱えないので Scribus を2日ほど使ってみましたがこれで書籍を作るのは正直かなりシンドいといった印象です。ベジェ使いにくいしリドゥ効かない部分あるしでマジで心が折れそう。

結局、書き慣れた AsciiDoc で原稿を書いてあとから漫画のページや表紙等を Scribus で合成する方針に変更。それも無理ならあとは GhostScript なり ImageMagickを駆使するしかない…。漫画はアナログで書いたものをスキャナで取り込んで Krita でベタとか入れる予定。

形式(コピ本 or オフセ本、カラー or モノクロ etc)や価格もまだまだ未定です。何より運営様の趣旨に沿わないことや抽選で外れる可能性もあるのでサークルとして出られるかどうかはわかりません。

不安しかない(;´Д`)

LoRa モジュール RAK811 WisDuo Lora Module で TTN に接続する

$
0
0

SX1276 と STM32L を搭載した RAK 社製の LoRa モジュールを AliExpress で入手した。AK811 を選んだ理由は下記の通り。

f:id:mattintosh4:20190822175421p:plain
RAK811 WisDuo LoRa Module

  • 小さい(大事)
  • 値段が安い(だいたい $15 くらい)
  • ARM 環境での開発にちょっと興味があった

RAK811 は ARM 開発環境が無くても AT コマンドで LoRaWAN や LoRaP2P の設定ができるようなので今回は AT コマンドで遊んでみる。

RAK811 に関する情報収集

物は届いたのでまずは情報収集から始めた。

  • ピンヘッダは 2 mm ピッチなのでそのままではブレッドボード等に挿すことはできない。XBeeのピッチ変換基板が流用できるっぽい?(海外掲示板情報)
  • ドキュメントにはファームウェアの更新方法が記載されているが、3.0.0.x 系の場合は BOOTピンを使わなくてよい。(ドキュメントには If the firmware of your RAK811 WisNode is V3.0.0.0 or a newer one, just jump this section.と書かれている)
  • ファームウェアの更新には RAK LoRaButton Upgrade Tool というソフトを使うがこれが Windowsしか対応していない様子(Wine でもなんとかできるかも)

ブートモードからノーマルモードに戻せない

これを先に書いておきたい。picocomコマンドで at+set_config=device:bootを送ってブートモードに移行すると AT コマンドを受け付けてくれなくなるため、at+runを送ってノーマルモードに戻すということができなくなる。この状態になってしまった場合はシェルのリダイレクトを使って at+runを書き込むことでノーマルモードに戻すことができる(ここでの USB シリアルアダプタのパスは /dev/ttyUSB0だが環境によって異なる)。ArduinoIDEのシリアルコンソールで改行コードを Both NR & CRに設定して AT コマンドを叩くという方法でも OK。何故か picocomのときはこうなる。

$ printf 'at+run\r\n' >/dev/ttyUSB0
Stop Boot Mode


========================================================
______  ___   _   __  _    _ _          _               
| ___ \/ _ \ | | / / | |  | (_)        | |              
| |_/ / /_\ \| |/ /  | |  | |_ _ __ ___| | ___  ___ ___ 
|    /|  _  ||    \  | |/\| | | '__/ _ \ |/ _ \/ __/ __|
| |\ \| | | || |\  \ \  /\  / | | |  __/ |  __/\__ \__ \
\_| \_\_| |_/\_| \_/  \/  \/|_|_|  \___|_|\___||___/___/
========================================================
********************************************************
RAK811 Version:3.0.0.3.H
********************************************************
========================================================

ファームウェアの更新

購入時のファームウェアは 3.0.0.0 だったが、一部のコマンドの改行がおかしかったので 3.0.0.3.H に更新した。ここでは RAK LoRaButton Upgrade Tool V1.0 を使用してファームウェアを V3.0.0.0.H から V3.0.0.3.H へ更新する。

最新のファームウェアは下記のページからダウンロードできる。

USB シリアルアダプタとの接続は VCCGNDTXRXのみで BOOTは接続不要。シリアル接続時の設定は下記の通り。

  • ボーレート: 115200
  • フローコントロール: オフ
  • パリティ: オフ
  • データビット: 8
  • ストップビット: 1

ここでは picocomコマンドを使用するが、ArduinoIDEのシリアルコンソールでも設定可能。ローカルエコーを有効にしておかないと入力したコマンドが見えないので注意(見えなくても慣れればそのまま操作できるけど)。

Terminal

$ picocom -b 115200 --echo /dev/ttyUSB0

まずはブートモードに変更する。

AT Command

at+set_config=device:boot

Result

work in Boot mode now...
<BOOT MODE>

ブートモードに設定できたら Ctrl + aCtrl + xpicocomを終了する。この状態で RAK LoRaButton Upgrade Tool で新しいファームウェアRUI_RAK811_V3.0.0.3.H.bin等)を選択して[Start]を押せば新しいファームウェアが書き込まれる。

macOSLinuxの場合はどうするのか?

Windows 10 の評価版などを入手して VirtualBoxにインストールしてホストの USB シリアルポートをバイパスさせることでゲストの Windows 10 から RAK LoRaButton Upgrade Tool を使って書き込みができる。Wine でもなんとかできるかも。

stm32flash についてはまだ試していない。

TTNへの接続(OTAA)

デフォルトでは OTAA モードになっているが ABP でもほとんど変わらない。

まずは get_config=lora:statusで現在の状態を確認する。

AT Command

at+get_config=lora:status

Region が AS923 になっていないのと DevEUI、AppEui、AppKey などが設定されていないのでこれらを設定していく。

Result

OK.
*************************************************
==============LoRaWAN Status List================
Region: EU868
Join_mode: OTAA
DevEui: 0000000000000000
AppEui: 0000000000000000
AppKey: 00000000000000000000000000000000
Class: A
Joined Network:false
IsConfirm: false
Work Mode: LoRaWAN
AdrEnable: true
EnableRepeaterSupport: false
RX2_CHANNEL_FREQUENCY: 869525000, RX2_CHANNEL_DR:0
RX_WINDOW_DURATION: 3000ms
RECEIVE_DELAY_1: 1000ms
RECEIVE_DELAY_2: 2000ms
JOIN_ACCEPT_DELAY_1: 5000ms
JOIN_ACCEPT_DELAY_2: 6000ms
Current Datarate: 5
Primeval Datarate: 5
ChannelsTxPower: 0
UpLinkCounter: 0
DownLinkCounter: 0
AntennaGain: 2.15
===================List End======================
*************************************************

Region の設定

周波数は下記のコマンドだけで設定できる。設定可能な値は EU868EU433CN470IN865EU868AU915US915KR920AS923。日本で使用できるのは AS923

AT Command

at+set_config=lora:region:AS923

デフォルトのデバイス EUI が返ってくるが TTNのコンソールで発行できるので控えておかなかったとしても問題はない。

Result

DEFAULT DEV_EUI = 9B0100089D010008
Selected LoRaWAN 1.0.2 Region: AS923
Band switch success.
OK

Region が変更されたか確認する。

AT Command

at+get_config=lora:status

Region が AS923に変更されている。周波数の値も 923200000になっている。

Result

OK.
*************************************************
==============LoRaWAN Status List================
Region: AS923
Join_mode: OTAA
DevEui: 0000000000000000
AppEui: 0000000000000000
AppKey: 00000000000000000000000000000000
Class: A
Joined Network:false
IsConfirm: false
Work Mode: LoRaWAN
AdrEnable: true
EnableRepeaterSupport: false
RX2_CHANNEL_FREQUENCY: 923200000, RX2_CHANNEL_DR:2
RX_WINDOW_DURATION: 3000ms
RECEIVE_DELAY_1: 1000ms
RECEIVE_DELAY_2: 2000ms
JOIN_ACCEPT_DELAY_1: 5000ms
JOIN_ACCEPT_DELAY_2: 6000ms
Current Datarate: 5
Primeval Datarate: 5
ChannelsTxPower: 0
UpLinkCounter: 0
DownLinkCounter: 0
AntennaGain: 2.15
===================List End======================
*************************************************

バイス EUI、アプリケーション EUI、アプリケーションキーの登録

TTN Console でデバイスを登録したら各値を控えておく。EUI は 16 桁、KEY は 32 桁の 16 進数。

dev_eui: 9B59615D543BC6F3
app_eui: 240A0F2375D286F8
app_key: 62DC6A9880FBE606F3503DB057946817

バイス EUI の登録

AT Command

at+set_config=lora:dev_eui:9B59615D543BC6F3

Result

OK

アプリケーション EUI の登録

AT Command

at+set_config=lora:app_eui:240A0F2375D286F8

Result

OK

アプリケーションキーの登録

注:OTAA の場合は lora:app_key、ABP の場合は lora:apps_keyなので間違わないように注意。

AT Command

at+set_config=lora:app_key:62DC6A9880FBE606F3503DB057946817

Result

OK

設定を確認する

EUI などが設定されているか確認する。「Joined Network」はまだ false

AT Command

at+get_config=lora:status

Result

OK.
*************************************************
==============LoRaWAN Status List================
Region: AS923
Join_mode: OTAA
DevEui: 9B59615D543BC6F3
AppEui: 240A0F2375D286F8
AppKey: 62DC6A9880FBE606F3503DB057946817
Class: A
Joined Network:false
IsConfirm: false
Work Mode: LoRaWAN
AdrEnable: true
EnableRepeaterSupport: false
RX2_CHANNEL_FREQUENCY: 923200000, RX2_CHANNEL_DR:2
RX_WINDOW_DURATION: 3000ms
RECEIVE_DELAY_1: 1000ms
RECEIVE_DELAY_2: 2000ms
JOIN_ACCEPT_DELAY_1: 5000ms
JOIN_ACCEPT_DELAY_2: 6000ms
Current Datarate: 5
Primeval Datarate: 5
ChannelsTxPower: 0
UpLinkCounter: 0
DownLinkCounter: 0
AntennaGain: 2.15
===================List End======================
*************************************************

LoRa ネットワークに JOIN する

EUI の準備などができたので LoRa ネットワークに JOIN する。

AT Command

at+join

Result

OTAA:
DevEui:9B59615D543BC6F3
AppEui:240A0F2375D286F8
AppKey:62DC6A9880FBE606F3503DB057946817
OTAA Join Start... 
OK
[LoRa]:Joined Successed!

成功すれば TTNの Console にアクティベーションのログが残っているはず。電源を切っても復帰すれば自動的に JOIN してくれる。

TTNにデータを送る

ドキュメントによれば at+sendは 50 bytes まで 16 進数でなければならないとある。適当に 1 バイトのデータを送ってみる。

AT Command

at+send=lora:1:00

Result

OK
[LoRa]: Unconfirm data send OK

データタブで受信できているか確認する。

/// image ///

デコーダを設定して値を整形する

TTNには Payload Formats という機能があり、値を変換したりすることができる。下記はデコーダのデフォルトサンプル。

Payload Formats (Decoder)

function Decoder(bytes, port) {// Decode an uplink message from a buffer// (array) of bytes to an object of fields.var decoded = {};

  // if (port === 1) decoded.led = bytes[0];return decoded;
}

サンプルを消して単純に数値を文字に変換する処理を入れてみる。返り値はオブジェクトで返す必要がある。

Payload Formats (Decoder)

function Decoder(bytes, port) {var a = [];
  for (var i=0; i<bytes.length; i++) {
    a.push(String.fromCharCode(bytes[i]));
  }return{
    message: a.join("")
  }}

シェルで Hello, world!という文字列を 16 進数に変換する。

Terminal

$ printf 'Hello, world!' | hexdump -e '50/1 "%02x"' | tr -d ' '
48656c6c6f2c20776f726c6421

Hello, World!を 16 進数に変換した結果を at+sendTTNに送る。

AT Command

at+send=lora:1:48656c6c6f2c20776f726c6421

データタブで確認すると文字列に変換された結果が出てくる。

//// images ////

Shell や Pythonからデータを送ってみる

シェルからは CR + LFを末尾に付けてデータを書き込むだけ。応答を catで読む場合は少し待ち時間を入れる。

$ printf 'at+send=lora:1:00\r\n' >/dev/ttyUSB1; sleep 1; cat /dev/ttyUSB1; sleep 3; cat /dev/ttyUSB1
OK
[LoRa]: Unconfirm data send OK

Pythonでは serialモジュールを使う(PIP を確認したら RAK811 用のモジュールもあるっぽい)。write()に渡すデータはバイナリになってなければならない。応答は read()または read(n)readline()で読み取ることができる。

import serial
s = serial.Serial("/dev/ttyUSB0", baudrate=115200, timeout=10)
s.write(b"at+send=lora:1:00\r\n")
s.readline()

AT コマンド一覧

at+join

Start to join LoRa network.

LoRa ネットワークに参加する。一度 at+joinすると電源を切っても設定が保持される(何日持つかは不明)。

at+run

Stop boot mode and run as normal. It is valid when the device works in boot mode.

ブートモードを停止してノーマルモードでは動作させる。デバイスがブートモードのときに有効。

at+version

Get the current firmware version number.

現在のファームウェアバージョン番号を得る。

OK3.0.0.3.H

at+send=lora:<PORT>:<HEX>

Send a customized data.

  • <PORT>: LoRa port
  • <HEX>: The data which you want to send. The limited length is 50 bytes, and the data must be in HEX format.

at+send=lorap2p:<HEX>

Send data through LoRaP2P. This AT command is valid when it works in LoRaP2P mode.

get_config=device

at+get_config=device:status

Get all infomation about the device's hardware components and their current status.

バイスのハードウェアに関する情報を表示する。

OK.
*************************************************
===============Device Status List================
Board Core:  RAK811
MCU:  STM32L151CB_A
LoRa chip:  SX1276
===================List End======================
*************************************************

set_config=device

at+set_config=device:boot

Let the device work in boot mode.

ブートモードとして動作させる。

at+set_config=device:restart

After set, the device will restart.

再起動する。

OK,restart ...

at+set_config=device:sleep:<MODE>

After setting, the device will go to sleep mode or wake up immediately.

バイスをスリープ、またはただちに起動させる。

  1. wake up
  2. sleep

get_config=lora

at+get_config=lora:status

LoRa に関する情報を表示する。(PDF 未記載)

at+get_config=lora:channel

It will return the state of all LoRa channels, then you can see which channel is closed and which channel is open very clearly.

OK.Max_nb_chs=16:
* 0,on,923200000,0,5;
* 1,on,923400000,0,5;
* 2,on,923600000,0,5;
* 3,on,923800000,0,5;
* 4,on,924000000,0,5;
* 5,on,924200000,0,5;
* 6,on,924400000,0,5;
* 7,on,924600000,0,5; 
  8,off,923600000,0,5;
  9,off,923800000,0,5;
  10,off,924000000,0,5;
  11,off,924200000,0,5;
  12,off,924400000,0,5;
  13,off,0,0,0;
  14,off,0,0,0;
  15,off,0,0,0;

*上記は at+set_config=lora:region:AS923時の結果を整形したもの

set_config=lora

at+set_config=lora:adr:<MODE>

Open or close ADR function of LoRa Node.

0: Close ADR 1: Open ADR

at+set_config=lora:app_eui:<VALUE>

Set the application EUI for OTAA.

at+set_config=lora:app_key:<VALUE>

Set the application key for OTAA.

at+set_config=lora:apps_key:<VALUE>

Set the application session key for ABP.

at+set_config=lora:ch_mask:<NUM>:<MODE>

Set a certain channel on or off. <NUM>: The channel number, and you can check which channel can be set before you set it. <MODE>: 0 off, 1 on

at+set_config=lora:class:<NUM>

Set the class for LoRa.

  1. Class A
  2. Class B
  3. Class C

at+set_config=lora:confirm:<NUM>

Set the type of messages which will be sent out through LoRa.

  1. unconfirm
  2. confirm

at+set_config=lora:dev_addr:<HEX>

Set the device address for ABP.

at+set_config=lora:dev_eui:<HEX>

Set the device EUI for OTAA.

at+set_config=lora:dr:<NUM>

Set the DR of LoRa Node.

<NUM>: The number of DR. Generally, the value of X can be 0~5. More details, please check the LoRaWAN 1.0.2 specification.

at+set_config=lora:join_mode:<NUM>

Set the join mode for LoRaWAN.

  1. OTAA
  2. ABP

at+set_config=lora:nwks_key:<VALUE>

Set the network session key for ABP.

at+set_config=lora:region:<VALUE>

Set the region for LoRa.

  • EU868
  • EU433
  • CN470
  • IN865
  • EU868
  • AU915
  • US915
  • KR920
  • AS923

at+set_config=lora:work_mode:<NUM>

Set the work mode for LoRa.

  1. LoRaWAN
  2. LoRaP2P
  3. Test Mode

at+set_config=lorap2p:X:Y:Z:A:B:C

Set the parameters for LoRa P2P mode. This AT command is valid when the work mode is LoRaP2P.

  • X: Frequency in Hz.
  • Y: Spreading factor.
  • Z: Bandwidth
    • 0: 125 kHz
    • 1: 250 kHz
    • 2: 500 kHz
  • A: Coding Rate
    • 1: 4/5
    • 2: 4/6
    • 3: 4/7
    • 4: 4/8
  • B: Preamble Length (5-65535)
  • C: Power in dbm (5-20)

書式に誤りがある場合

以下のような応答が返ってくる。

  • No AT Command was found.
  • AT format error.

at+sendでデータサイズがオーバーしている場合は下記のメッセージが返ってくる。

  • String over max length <256 Bytes>.

LoRaP2P モードで使うには

RAK811 Breakout Board を2つ用意する。

リージョンを設定する。

at+set_config=lora:region:AS923

LoRa の動作モードを LoRaP2P に設定する。

at+set_config=lora:work_mode:1

周波数などを設定する。

set+set_config=lorap2p:869525000:7:0:1:5:5

どちらかの RAK811 Breakout Board からデータを送る。

at+send=lorap2p:1234567890

同人イベントにサークル参加してきました

$
0
0

以前お知らせした通り、東方Projectの同人イベント「第六回博麗神社秋季例大祭」にサークル参加してきました。

色々あって辞退することも検討していたのですが、頑張って参加して良かったなと思っています。当日お越しいただいた皆様ありがとうございました。

当日はこんなコピー本を頒布しておりました。

台風19号が来る前にスキャナーが届いたので今後の自分のためにレポート的なものを残しておこうかなとかなんとか。

以下、素人の下手な絵がダラダラと続きますので苦手な方は閲覧をお控えください。

2019年 絵を描き始める

3D のモデリングをしてみたいけど 2D からしっかりやった方がいいよなぁ、ということで練習のために『深夜の真剣お絵描き60分一本勝負(通称ワンドロ)』というものを始めることにしました。派生で『艦これ版』とかもありますが、Twitterやってる方なら見たことあるのではないでしょうか。絵を描くのなんて小学生以来なので完全初心者スタートです。

この辺の落書きは Pixiv にあります。

東方Projectの同人誌とかはいくつか持っているのでなんとなくキャラはわかるんですが、実際絵を描くとなると難しい。というのも東方Projectは原作絵が少ないためネットやお店で見かける絵は大抵が二次創作なんですね(公式書籍なんかもあったりしますが絵師さんが描いてたりします)。他のアニメやゲームなんかに比べると元絵が少ないので本当に頭を使います。

ワンドロをやりつつ、お次は『ポーズマニアックス』の『30秒ドローイング』ですね。3D の人体模型を見ながら模写するってやつです。普段あまり人体とか気にせず見てますが改めて見ると人体って面白いなぁと思います。30秒は無理なので60秒か90秒で数日やってました。

f:id:mattintosh4:20191011175830p:plain
ポーズマニアックス(2019年4月22日)

そしてこのあたりを境目に絵を描くのを辞めました(早

仕事でメンタルやられてしまったのと、万年筆に嵌って字ばっかり書いてたんだと思います。6月11日に万年筆インク『色雫彩 - 霧雨』を買ったので霧雨魔理沙っぽい何かを描いていたようです。

f:id:mattintosh4:20191011181850p:plain
落書き(2019年6月11日)

かゆ…

うま…

表紙を考え始める

8月半ばになってもモチベーションが上がらないものの「最低限、表紙が無いと告知も何も出来ないな…」と思ったので表紙に手を付けることにしました。A5のノートにざっくりとイメージを描いてみる。魔理沙がエンジニアという設定なので楽天とかでオフィスカジュアルな服を見てみたけどあまりピンと来るものがなく衣装はとりあえずという感じ。(日本のIT現場ってだいたい男しかいないからね)

f:id:mattintosh4:20191011142955p:plain
表紙ボツ案ラフ(2019年8月20日

どうも「ペンタブの描いてる場所と描画場所が違う」というのに慣れなくて出来ればアナログでやりたかったんですが、デジタルの方が何かと楽なので頑張ってデジタルを使うことに。ペンタブは昔、プレゼンとかで使えれば楽だなと思って買ったもののほとんど使ってなかったワコムの『CTH-490』(元 Bamboo シリーズの一番小さいやつ)。

スキャナを持っていないので iPhoneで撮影してペイントソフトに取り込む。Linuxに対応しているペイントソフトはほとんど無いので Krita を選択。色塗るわけじゃないし、線画ならなんとかなるでしょ。ブラシとか何を使ったらいいのかよくわからなかったのでとりあえず "Ink-3 Gpen"を使ってみる。ペンタブを真面目に使うのも初めてだったのでトレースするだけなのに滅茶苦茶手こずった。このとき平行定規などの機能を知って遊んだりしてた。

f:id:mattintosh4:20191011143047p:plain
表紙ボツ案線画(2019年8月20日

「よーし、とりあえず表紙案も出来たし、受かるかどうかもわからないけど何とかなるだろ!」

とか思っていました。

参加証が届く

当落通知はもう少し早く出ていたんですが受かってしまいました。サークルスペースが「うぅ、お腹痛いブー(う07b)」だったって言うね。

よし、本文やるぞ!あれ?表紙のキャラデザで絵が描けない…左綴じ…コマ割り…

とりあえずで作った表紙だけど、実際本文をやってみようと思うと自分の力量不足で表紙のキャラデザで絵が描けないということに気づいた。アニメやゲームではキャラの設定画を用意されていたりするけど、ああいうものを作っておいた方がいいんだろうなとは思ったもののとりあえず表紙のラフを目の前に貼り付けて「本文描いてるうちにキャラデザ決まるだろ」なんて思いながら本文を考えることにした。

当初は普通の漫画を予定していたのだけど、技術書と言えばほとんどが左綴じだが、一般的な漫画は右綴じである。つまり左綴じ用にレイアウトを考えなくてはならない。参考になる資料が同人即売会イベントのカタログに収録されているちょっとした漫画の部分くらいしか無く、コマ割り自体結構悩むのに左綴じのコマ割りが出来なかった。「両面表紙で技術書は左から読んで、漫画は右から読めばいいのでは!?」というアホな構成も考えたけど特殊過ぎるのでやめた。

四コマなら左綴じでもなんとかなる気がしたので四コマで考えることにした(どんどんハードルが下がる)。四コマと言えば『起承転結』が肝心だけどその辺を気にする余裕も無くなってきた。

f:id:mattintosh4:20191011151637p:plain
本文ラフ①

久しぶりに描いたらまた絵柄が変わってしまったので多分キャラのデザインをちゃんと考えようと思ったんだろう形跡が残っていた。日付が9月12日なので既にイベントまで一ヶ月を切っている。

f:id:mattintosh4:20191011151753p:plain
落書き(2019年9月12日)

とりあえず髪の毛は細めのものを束ねることにして本文を進めるがこれまた絵柄が安定しない。どうも三頭身とかが描けないっぽい。

f:id:mattintosh4:20191011153506p:plain
本文ラフ②

キャラデザをちゃんと考える

時間も技術もなくて流石に危うくなってきたので東方鈴奈庵の絵柄を参考にさせてもらうことにした。髪型で悩んでいる節があったので髪型さえ決まればなんとかなる気がしたんだと思う。衣装も考えている余裕がなかったので鬼形獣のものを参考にした。

f:id:mattintosh4:20191011153810p:plain

f:id:mattintosh4:20191011153848p:plain

キャラデザ

表紙も再考。何故か二頭身になった。ちなみにこの後また絵柄が変わったのでこの絵柄の魔理沙は表紙にしか出てこない。

f:id:mattintosh4:20191011142851p:plain

f:id:mattintosh4:20191011142857p:plain

表紙再考案

Krita に取り込んでアイコンと表紙を描いてみる。この辺からちょっとやる気出てきた気がするけど既に9月27日。

素材作成と表情の練習用に顔のパーツを変えたものをいくつか作った。ひとつずつ保存するの大変だったけど楽しかった。

f:id:mattintosh4:20191011160639p:plain
魔理沙アイコン

本文との戦い

なんとかキャラデザが決まったので本文のラフを描く。自分は右利きなので本来であれば左向きの顔の方が描きやすいのだが、左綴じを意識してしまっているせいか右向きが多い。

f:id:mattintosh4:20191011161117p:plain
本文②ラフ

Krita に取り込んでトレースしていく。ノートではスペースが無かったので見えない部分も含めて構図を考えてみるがなんか違う気がしてなかなか進まない。

f:id:mattintosh4:20191011162935p:plain

f:id:mattintosh4:20191011163352p:plain

Krita で線画

ちょっと本文の線画を置いといてパース考えながら練習してみる。

f:id:mattintosh4:20191011164714p:plain

f:id:mattintosh4:20191011164720p:plain

練習①

f:id:mattintosh4:20191011165029p:plain

f:id:mattintosh4:20191011165053p:plain

練習②

f:id:mattintosh4:20191011165359p:plain

f:id:mattintosh4:20191011165420p:plain

練習③

f:id:mattintosh4:20191011165646p:plain

f:id:mattintosh4:20191011165713p:plain

練習④

f:id:mattintosh4:20191011170136p:plain

f:id:mattintosh4:20191011170203p:plain

練習⑤

f:id:mattintosh4:20191011170250p:plain

f:id:mattintosh4:20191011170317p:plain

練習⑥

お前はデフォルメキャラで描きたくないんかい!って突っ込みたくなる。そして写真やってた癖にパースわかってないのな…。迷い線は少なくなってきた気がするけど、どんな絵を描きたいのかわからなくなってきたので一旦練習を止めて本文の別のページに手を付けることにした。

2日後

改めて練習してみると2日前と絵柄が変わってしまった…。アタリが適当過ぎてあまり役に立っていない。

f:id:mattintosh4:20191011172111p:plain

f:id:mattintosh4:20191011172139p:plain

練習⑦

ポーズマニアックスをやってたせいか、これくらいの頭身の方が描きやすいっぽい。

新しいデフォルメを考える

本文でデフォルメキャラを使うコマがあったがラフのはコレジャナイ感がしたので新しく考えることにした。

f:id:mattintosh4:20191011161343p:plain
本文③ラフ

「なんかもうちょっと可愛らしい感じの…う〜ん」って悩みながらラフをカリカリ…。デフォルメって描き慣れていないので本当に難しい。

f:id:mattintosh4:20191011171021p:plain
デフォルメ(ラフ)

まぁまぁいい感じのが出来た気がする。後ろ髪はバランスのいい線が描けず時間も無かったので今回は省略することにした。

f:id:mattintosh4:20191011171352p:plain
デフォルメ(線画)

まぁまぁ衣装もいい感じで描けた気がする。これ描いてるのがイベント3日前なので相当焦ってた気がする。

猫耳つけてみたら案外よかったので猫耳バージョンを裏表紙で使った。

印刷

秋葉原製作所さんに行ってセルフ製本してきた。店員さんが丁寧にサポートしてくれたのでスムーズに出来た。表紙と本文を分けてしまったので表紙を印刷後に裁断機でフチを落としてそのあと別のプリンターで中綴じっていうちょっと面倒なことになったけど。

今回の作業は Mac miniでやってたんだけどメモリが 4 GB しか無かったのでモノクロ 350 dpi で作業してたんだけど小さいアイコンもちゃんと表情がわかるくらい綺麗に出てくれたので助かった…。

イベント当日

あんまり早く行ってもすることが無いのでゆっくり行った。サークル登録しに行ったときに登録証が無かったときは焦ったけど通行証と一緒に付いてた…。

一応、前日にセリアでイーゼルとクラフト紙を買っておいたのでそれっぽく設営。秒で終わったけど。

開場後はカタログ見たりして時間潰してたんだけど1時間に1、2人くらいのペースで足を運んでくれる人がちらほら。昼過ぎまでソロ参加だったからずっとスペースにいたけど人間ウォッチングとかしてたりしたらあっという間に時間が過ぎてたな。

次回に向けて

冬コミも申し込んだけど定員割れすることは無いし落ちる可能性は高いでしょうね。来年の博麗神社例大祭は静岡開催なのでちょっと難しそうだし。

とりあえず今回のプレビュー本の完成版を作って、次回はイラスト本が作れればいいかなぁと思っています。イラスト本が簡単ってわけではないんだけど、漫画は色々と考えなきゃいけないことが多い…。今は東方Projectしか描いてないので他のジャンルも描いてみたりしたいですね。まずはメンタル回復させて絵を描くことを日常的にしなくてはいけないわけですが…。

身内で絵を描く交流が出来れば楽しそうなんだけど周りにいないので寂しい…(´・ω・`)

それでは台風19号にお気をつけてまた今度。

VirtualBox に macOS Catalina 開発環境を作る

$
0
0

不具合報告多数の Catalina さん。開発用なら問題ないでしょうが実機に入れる気にはならないですね。

いつも通りインストール用の ISO 作成。Mojave のときに作っておいたものがそのまま使えたので変数だけ書き換え。8 GB を超えているのでイメージサイズは 9 GB に変更。

#!/bin/bashset-eset-uset-xname=Catalina
tempfile=$(mktemp -u)
hdiutil create -size 9g -fs HFS+J -layout SPUD ${tempfile}
hdiutil attach ${tempfile}.dmg -noverify-nobrowse-mountpoint /Volumes/Install\ macOS\ ${name}
sudo /Applications/Install\ macOS\ ${name}.app/Contents/Resources/createinstallmedia --nointeraction--downloadassets--volume /Volumes/Install\ macOS\ ${name}
hdiutil detach /Volumes/Install\ macOS\ ${name}
hdiutil resize -size$(hdiutil resize -limits ${tempfile}.dmg | awk 'END { print $1 }')b ${tempfile}.dmg
hdiutil convert ${tempfile}.dmg -ov-format UDTO -o"Install macOS ${name}"rm${tempfile}.dmg
mv Install\ macOS\ ${name}.{cdr,iso}

最初のインストール中に再起動してまた ISO から起動するので一旦ディスクを取り外して VMを再起動する。インストール完了後、再起動するが VirtualBoxが APFS のパーティションを認識出来ないため再び ISO をセットしてインストーラーのユーティリティからターミナルを起動する。

APFS を読み取れるようにインストーラーに付属されている apfs.efiEFIボリュームにコピーする。ついでに自動起動するように startup.nshを作成するが、システムボリュームの UUID を調べておく必要がある。例えばディスクの初期化時に名前を Macintosh HDとした場合は disk1s5がソレ。

f:id:mattintosh4:20191017161134p:plain
macOS Catalina

volume=disk1s5

# ボリュームの UUID を取得uuid=$(diskutil info ${volume}| awk '/Volume UUID:/ { print $NF }')# EFI ボリュームをマウント
diskutil mount /dev/disk0s1

# APFS EFI ファイルを EFI ボリュームにコピー
cp /Volumes/macOS\ Base\ System/usr/standalone/i386/apfs.efi /Volumes/EFI

# startup.nsh を作成
cat >/Volumes/EFI/startup.nsh <<!load fs0:\apfs.efimap -rfs1:\${uuid}\System\Library\CoreServices\boot.efi!

案の定、糞重い。ディスクイメージの使用サイズは 26 GB くらい。40 GB くらいで用意しておかないと何も出来なさそう。

f:id:mattintosh4:20191017161849p:plain
macOS Catalina


EasyWine 上の AviUtl で x264guiEx を使いたい場合

$
0
0

なんかエラーが出ると言ってる人をよく見かけるので。x264guiEx の作者様の手動導入の説明をちゃんと読めば方法は書いてあるのだけど読んでないのでしょうね。ここを見つけた人はだいたい libmono がうんちゃらかんちゃらだと思います。

作者様のブログのコメント欄を見ると Macなのに質問している人がいるし…。作者様にはご迷惑をおかけして申し訳ないです。

結論から言うと.NET Framework 4.5 を入れればいいだけです。(動画部分に関しては)

.NET Framework 4.5 のインストール方法

自分で入れることも出来るけど細かい設定が面倒なので同梱してある winetricksを使うことを推奨します。EasyWine64.appの場所は人それぞれだと思いますが、EasyWine64.app/Contents/Resources/wine/binに必要なものが入っています。

以下、ターミナルで作業。

PATH環境変数EasyWine64.appに内蔵してある binディレクトリを追加します。これは人それぞれなので自分の環境に合わせてください。$(getconf PATH)の部分は余計なものを引っ張ってこないために入れてますが /usr/bin:/binとかでもいいです。

Terminal

PATH=~/Applications/EasyWine64.app/Contents/Resources/wine/bin:$(getconf PATH)

EasyWine で使用している WINEPREFIX を WINEPREFIX環境変数に設定します。

Terminal

export WINEPREFIX=~/Library/Caches/Wine/prefixes/default64

Winetricks で .NET Framework 4.5 をインストールします。

Terminal

winetricks dotnet45

インストーラのダウンロードが完了するとそのままインストール画面になるので[次へ]を押して進めていきます。この処理には数分かかることがあります。

f:id:mattintosh4:20191023013556p:plain
Winetricks - .NET Framework 4.5

f:id:mattintosh4:20191023013616p:plain
Winetricks - .NET Framework 4.5

f:id:mattintosh4:20191023013639p:plain
Winetricks - .NET Framework 4.5

もしかしたらターミナルが winetricksを実行したまま止まっているかもしれませんがそのままにしておいて aviutl から x264guiEx の設定画面が表示できるか確認してみましょう。

qaac を使いたい場合

qaac の動作には下記の3つのライブラリが必要なはず。QuickTime for Windowsは既に古くなっているので新しいバージョンのエンコーダを使いたい場合は iTunesインストーラから取り出す必要がある。個別の取り出し方に関しても下記リンク参照。よくわからない場合は neroAacEnc.exe をウェブアーカイブから取得して pluginsディレクトリに突っ込んだ方が早いQuickTime for Windowsの最終版と neroAacEnc 1.5.1 の品質については比較していないので知らないが neroAacEnc 1.5.1 の方が良さそう)。

mattintosh.hatenablog.com

mattintosh.hatenablog.com

(メモ)無音を追加したい

音声が付いてないとダメな場合は ffmpeganullsrcで無音を追加すればよい。

Terminal

ffmpeg \-f lavfi -ianullsrc=channel_layout=stereo:sample_rate=44100\-i foo.mp4 \-c:v copy \-c:a aac \-shortest\
    bar.mp4

Twitter に PNG をアップロードするときに JPEG に変換されない画像を作る

$
0
0

2019年2月11日より TwitterPNGイメージをアップロードすると場合によっては JPEGイメージに変換されてしまうようになった(公式アナウンス)。いままであまり気にしてなかったのだけど久しぶりに macOSを使っていてスクリーンショットをダイレクトにアップロードする際に気になるようになってしまった。

PNGのままアップロードしたいという場合は色数の少ない PNG8 に変換したり長辺のサイズを 900 px 以下にしなければならない。できるだけ綺麗な見た目で解像度を変えずに PNG32 や PNG24 から PNG8 に変換するために pngquantというプログラムを使う。pngquant はコマンドで使うプログラムだが macOSの場合は Automatorを使うことで Finder 上で PNG8 イメージに変換可能なアプリケーションを作成することができるし、Linuxはアプリケーションファイルを作成すればいいだけなので結構簡単に GUIからも使える。pngquant を通すことでファイルサイズが 1/2 〜 1/4 くらいになるのでそこまで過度に綺麗さを求めないイメージのファイルサイズを削減できる(これは1カ月の利用制限がある Hatena Fotolifeを使っているユーザとしても有り難い)。

下記は実際に pngquant を使って Twitterにアップロードした画像。多少ザラつきはあるものの十分実用範囲。

Linuxについては語る必要はないと思うのでここでは macOSでの話をする。

pngquant を用意する

pngquant 公式サイトから macOSの向けのバイナリをダウンロードする。

pngquant.tar.bz2を解凍して扱いやすい場所に移動する。(例えば自分のホームディレクトリにある Applicationsディレクトリなど)

パッケージマネージャを使っている場合はそちらからでも導入可能だが、MacPortsの方はバージョンが少し古い。

パッケージマネージャごとの pngquant バージョン(2019年10月23日時点)

パッケージマネージャpngquant バージョンインストールコマンド
Homebrew2.12.5 (July 2019)brew install pngquant
MacPorts2.12.2 (January 2018)sudo port install pngquant

"PNG8 変換クイックアクション"の作り方

Automatorを起動したらクイックアクションを新規作成する。クイックアクションは Finder などのアプリケーションで右クリックして表示したコンテキストメニューから作成した処理を実行させられるというもの。

編集画面が開いたら左の「ユーティリティ」メニューから「シェルスクリプトを実行」アクションをワークフローにドラッグするなりして追加する。設定のポイントは以下の部分。

  • ワークフローが受け取る現在の項目を「ファイルまたはフォルダ」に設定
  • 検索対象を「Finder.app」に設定
  • シェルスクリプトを実行」アクションの入力の引き渡し方法を「引数として」に設定

f:id:mattintosh4:20191023143907p:plain
Automator - シェルスクリプトを実行

以下の例では pngquant を ~/Applications/pngquant/pngquatに配置しているがそこは環境に合わせて変更すること。Automatorでは Finder.app の項目をファイルに限定することができないのでシェルの内部で弾くようにしておく(ディレクトリが渡されたら中身まとめて渡す、という処理を使いすることもできるがここではやらない)。pngquant のオプションはお好みで。

Automator - シェルスクリプトを実行 スクリプト

for f
dotest-f"${f}"||continue
    ~/Applications/pngquant/pngquant --force--speed1256"${f}"done

テストでは 219 KB のファイルが 66 KB まで縮小した。

作成したアクションは Finder でファイルを単一または複数選択して右クリックのコンテキストメニューから 「クイックアクション」を開くと実行できる。

f:id:mattintosh4:20191023154512p:plain
Finder - クイックアクション

"グレースケール PNG8 変換クイックアクション"の作り方

漫画やイラストなどをグレースケール化して PNG8 にしたい場合。pngquant にはグレースケール化のオプションが無いので ImageMagickを使う。pngquant はパイプでデータを受け取ることができるので一時ファイルは不要。グレースケール化に特定のチャネルを使いたい場合などは -channel-separateなどを併用する。接尾辞はカラーとの差別化のため -fs8g.pngになるようにしている。

以下は Homebrew で pngquant と ImageMagickをインストールしてある場合のスクリプト例。

Automator - シェルスクリプトを実行 スクリプト

for f
dotest-f"${f}"||continue
    /usr/local/bin/convert "${f}"-type GrayscaleMatte png:- \
    | /usr/local/bin/pngquant --speed1256 - \
    >"${f%.*}"-fs8g.png
done

テストでは 219 KB のファイルが 67 KB まで縮小した。

EasyWine の頒布を休止します

$
0
0

タイトルの通りですが、近々 EasyWine とその他派生物の頒布を休止します。再開次期は未定です。これに伴い過去の関連記事も順次終了していきます。

若干愚痴混じりなので気にされる方は読まずにブラウザを閉じることをおすすめします。

現状、macOS Catalina では Wine はまともに動きません。前々から次期 macOSでは 32-bit アプリケーションが廃止されると言われていましたが、それを認識していない方が多く、正直なところ煩わしい問い合わせが増えました。そもそも EasyWine の 64-bit 対応は Windowsアプリケーションを対象にしている話であって macOSを対象にした話ではありません。macOSはもうかなり前から 64-bit で動いています。

EasyWine を頒布することによってある程度の人が「素の Wine」に触れることなく Windowsアプリケーションを使っていたと思います。Wine を気軽に使えるように敷居を下げられたことは嬉しいですが、その反面、ユーザが素の Wine と直接向き合う機会を奪ってしまったとも思っています。もしかしたら EasyWine から使い始めて「今では自分で Wine をコンパイルしている」という方もいるかもしれません。

「ソフトのエンドユーザなんて根幹部分の開発している人の苦労なんざ知ったこっちゃないでしょ」というのが一般的な意見だと思います。自分も子供のときはそうでしたし。しかしこれでは Wine チームや CodeWeavers の方々に利益が生まれないですよね。素の Wine を使っていればバグレポートとかを送ってプロジェクトに貢献したりもするでしょうが、EasyWine を使っている場合はバグレポートどころか不満や文句を言われて終わりです。

いまの macOSは Homebrew があるし、昔ほど Wine の導入は困難ではないでしょう。実際、この前の検証では 30 分もあれば終わりました。何かあっても Homebrew のフォーラムでサポートが受けられるでしょう。

Miku Installer、Wineskin、Winebottler などなどいろいろな派生アプリケーションが生まれては開発が止まっていきました(久々に見たら Winebottler 更新されてた)。EasyWine も NXWine の頃から数えるともう 6 年以上ですかね。一般的なソフトウェアの開発と言えるような立派な開発はしてきませんでしたが、個人で無償でやっていくにはモチベーションも上がらないのでもう手放していいような気がしてきました。

最新のソースコードは下記に置いてあります。Xcode 8.3.3 が扱える Mojave 以前の macOSなら依存関係のソースコードやツールを集めればどの環境でもセルフビルドできるはずです。

github.com

先日発行した同人誌の中から、Homebrew のインストールから Wine のインストール、簡易的な文字化け対策までの部分を無償公開しておきます。

f:id:mattintosh4:20191023190932p:plain
Homebrew のインストール

f:id:mattintosh4:20191023190948p:plain
Wine のインストール

何らかのかたちで利益を得られるようであれば頒布を再開するかもしれませんし、技術書典やコミックマーケットなどのイベント限定で頒布したりするかもしれません。

今後は CrossOver や Homebrew の利用をご検討ください。

Vue.js で2つの配列からデータを取得する

$
0
0

Vue.js の勉強してるけどなんかなぁ…って感じ。どうも文法というか書式というかに馴染めない感じ。自分の頭がオブジェクト指向じゃないからなんだろうけど。MVVM の解説読んでみたけど初歩的なことやってないから View とか Model とかよくわからない。

さて、Elasticsearch に貯めたデータをほぼそのまま Vue.js に持ってきてるんだけども、設計のミスもあったせいでちょっと困った。

大抵の書籍の場合、一つの書籍に対して一人の著者が結び付く 1:1なんだけど、書籍やストアによっては一つの書籍に対して複数の著者が結びつく 1:nになっていることがある。

xpathで取り出しているせいもあって、初期段階では全ての項目が配列になっているところを、配列の長さが 1のものは文字列に変換する処理をかけていた。

1:1 のデータ

{"hits": {"_source": {"book_name": "五等分の花嫁",
      "author_name": "春場ねぎ",
      "author_url": "https://booklive.jp/focus/author/a_id/123817"
    }}}

1:n のデータ

{"hits": {"_source": {"book_name": "転生したらスライムだった件",
      "author_name": ["川上泰樹",
        "伏瀬",
        "みっつばー"
      ],
      "author_url": ["https://booklive.jp/focus/author/a_id/121592",
        "https://booklive.jp/focus/author/a_id/110906",
        "https://booklive.jp/focus/author/a_id/110907"
      ]}}}

Pythonであれば zip(author_name, author_url)で2つの配列を紐付けることができるんだけど Vue.js というか JavaScriptでその方法がわからない。

じゃあインデックスは一致してるんだから片方のインデックス使って参照すればいいんじゃないの、と思ったけど、1:1の方は文字列で入っているので v-forに入れてしまうと1文字ずつに分割されてしまう…Oh。

というわけで v-if="Array.isArray()"で条件分岐すればいいんじゃないかと思ったけどネット上にうまいことやってるお手本が無かった。個人的にはこういう情報がネットにあると嬉しいんだけどなぁと思う。言語によって説明が上手い人もいたりいなかったり。言語の好みはこういうところから分かれていくのだろうか。

v-forはインデックスも取れるようなので author_nameのインデックスを index変数に入れて、そのインデックスを使って author_urlの値を拾ってくる。

<!-- author_name が配列の場合 --><ul v-if="Array.isArray(hits._source.author_name)"><li v-for="author_name, index in hits._source.author_name"><a v-bind:href="hits._source.author_url[index]">{{ author_name }}</a></li></ul><!-- author_name が文字列の場合 --><ul v-else><li><a v-bind:href="hits._source.author_url">{{ author_name }}</a></li></ul>

Vue.js の公式サイトも翻訳されててまぁいいんだけどどうも説明の仕方が微妙。MDN はわかりやすいんだけどなぁ…。最近は文章読んでも理解できないし、いまから JavaScript思い出すのもしんどい…(;´Д`)

久しぶりに Web サイト作ってみたものの、内容が至極個人的なものなので見た目とか自分がわかればどうでもいいじゃんよって思うようになりこれ以上モチベーションが上がらない。

ebookman.ga

対象ストアも増えてきちゃったし。ていうかお前 Amazonしか使ってないじゃん?しかもランキングなら Kibana とか Grafana で推移見ながらの方が楽しいじゃない?とかなんとか。

昨日、ニュースに出ていた「アル」というサービスはとても良いものだと思う。自分にはこういうアイデア思いついたりとか実際に作ろうという行動力が無いのですごいなと思う。

alu.jp

www.itmedia.co.jp

さぁこの下がり続けるモチベーションをどうしようか…。

bash でランダムな三択とか乱数作ったりとか

$
0
0

シェルスクリプト書いてるときに外部コマンドを使わずにシェルだけでハッシュっぽいもの作れないかなと思ったので頭の体操。

bashには ${パラメータ:オフセット:長さ}という変数の展開方法があり、例えば ${パラメータ:オフセット:1}とすれば「"パラメータ"の n 番目を1個取り出す」ということができる。オフセットや長さの部分には算術式を用いることもできる。なお、オフセットはゼロから始まる。

bashには RANDOMという特殊変数があり、これは展開する度に 0 〜 32767 の数値がランダムで得られる。オフセットの値に関しては RANDOM変数を元の文字数で割った余りを使えば文字数以上の長さになることはない。

p=0123456789abcdef
echo${p:$((RANDOM%16)):1}

上の ${p:$((RANDOM%16)):1}の部分はいくつか書式が考えられるが上のがそこそこ短い書式。一番短いのは算術式を $[算術式]で書く方法だけど kshとかで動かなくなるのである程度移植性の高い $((算術式))がいいと思う。

# 普通${p:$((RANDOM%16)):1}# $(()) を $[] で置き換えたもの(移植性については謎)${p:$[RANDOM%16]:1}# 丁寧に書いた場合${p:$((${RANDOM} % 16)):1}

ある程度の長さを得たい場合はループさせればよいだけ。1文字ずつ printfしてもいいと思うけど最後にまとめてポンっと出力する方法。

p=0123456789abcdef
set -- # 位置パラメータをリセットfor ((i=0; i<64; i++))doset -- ${*}${p:$((RANDOM%16)):1}doneecho${*}

関数化すれば引数で長さ指定ができる。関数化するときは関数の定義を function(){( コード; )}のようにサブシェルで実行するようにしておいた方がいいかもしれない。というのもこの関数を for ((i=0; i<100; i++)); do rand_hex; doneみたいに呼び出すと関数の中で変数 iが常にリセットされて無限ループになる。lengthとか pdeclare -ireadonlyで保護するようにしておいた方がいいと思う。

rand_hex(){(
    length=${1:-8}# 引数がなければ長さ8に設定p=0123456789abcdef
    set --
    for ((i=0; i<length; i++))doset -- ${*}${p:$((RANDOM%16)):1}doneecho${*}
)}

まぁ uuidgenとかの方が早いですわな。

$ time for ((i=0; i<100; i++)); do rand_hex 8; done >/dev/null
real    0m0.187s
user    0m0.137s
sys     0m0.060s

$ time for ((i=0; i<100; i++)); do rand_hex 32; done >/dev/null
real    0m0.289s
user    0m0.188s
sys     0m0.113s

$ time for ((i=0; i<100; i++)); do uuidgen; done >/dev/null
real    0m0.166s
user    0m0.100s
sys     0m0.072s

固定長なら若干速い。

fake_uuidgen(){(
    : ${p:=0123456789abcdef}echo \${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}\${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}-\${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}-\${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}-\${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}-\${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}\${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}\${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}${p:$((RANDOM%16)):1}
)}
$ time for ((i=0; i<100; i++)); do fake_uuidgen; done >/dev/null
ddfb8a1a-5cf0-1541-5da0-9fe735f83e3a
93013969-61fe-c430-18bb-0092cb0c69ac
7c29e654-b11d-5418-62dd-c906e26160b8
:
中略
:
real    0m0.193s
user    0m0.132s
sys     0m0.071s

適当に64桁を10件ほど。精度の程は知らんけどシェルだけで適当な乱数欲しいときはこれで十分かな。

     1  91f26b3f3b340a6fb4ae252d334c63a4494801d9968a085069924444f8b4ac13
     2  c8e2771989fb9374476efd2b4951e47c0fcbe604cb3033e787c8e7f1c5a61037
     3  405eb6b8fae038b64651ab10b3a6cc1ee211ee676097a0274a235a87929f22eb
     4  2643f3cbdf1bf75487b5dc2ae78fb9225100437d69a73ae4b52e2bce7a5e786f
     5  b1600fd13dc36a19c15bdc3f25a5bffd5580f1eefdcd8d5b1044743373576441
     6  46457b497e72d6f2650dd78c7991eb13638c4c1bfc8562ee61ec0eb3bb1f9b26
     7  61729017c41b2e72d797341697168631cebf8396e9e6505dbe0e7b199298ceb1
     8  88d3a91c8d266c02e8ae75a6c3d6da6a06bdaa46f0b73cb9b3eed6c1d3c4d06c
     9  4c8b7d7cefa16e9877292e9927de7d20d946c7522726f0d349f53fe4ff859a60
    10  6c42f5c60b1c0c9daa9db899f892a41c098fae3cb41eeb670ba4859505217282

まぁそれなりにバラけてるのではなかろうか。











先頭2桁でグレースケール。










同じく 6 桁の 16 進数を取り出して RGB 値のように変換して総計を追加して CSVで書き出す。

for ((i=0; i<100; i++))doecho rand_hex 6done |
while readdoset -- $((16#${REPLY:0:2}))$((16#${REPLY:2:2}))$((16#${REPLY:4:2}))echo$1$2$3$(($1+$2+$3))done |
awk 'BEGIN { OFS="," } { print NR,$1,$2,$3,$4 }'
1,61,44,0,105
2,58,242,76,376
3,205,120,177,502
:
中略
:
98,43,3,9,55
99,223,91,110,424
100,66,251,228,545

んで gnuplotで見てみる。

gnuplot \
-e 'set datafile separator ","'\
-e 'plot "1.csv" using 1:2 with lines, "" using 1:3 with lines, "" using 1:4 with lines, "" using 1:5 with lines'\
-e 'pause -1'

f:id:mattintosh4:20191026085534p:plain
rand_hex

う〜ん…うまくバラけてるようなバラけてないような。一応 uuidgen の結果も見てみる。

f:id:mattintosh4:20191026091219p:plain
uuidgen

細かく見りゃ違うのかもしれんがパット見はあんまり差は無さそう。


本当は単に A B C のうちどれかをランダムで返してくれるだけでいいものを作っていたんだけどな…。

p=abc; echo${p:$((RANDOM%3)):1}

GNUbash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)

Viewing all 880 articles
Browse latest View live