bashのリダイレクトについて
bashで出力内容の出力先を制御する方法として用いられるリダイレクトだが,たいへん不可解で混乱しがちだと思う.
理論的に正しいかどうかはわからないが,私なりに理解した道筋をメモしておく.
標準出力に文字列 output を出し,標準エラー出力に error を出すコマンド output_error があるとする.
$ output_error
上記を実行すると,下記のように表示される.
一行目のoutputは標準出力,二行目のerrorは標準エラー出力である.
output error
では,下記のようにするとどうなるか.
$ output_error 2>&1 1> file.txt
error
ターミナルの表示は上記のようになり,file.txtには output が書き込まれている.
1> file.txt
は,通常は標準出力に出力されるものを file.txt に流せ,という指示である.
2>&1
は,標準エラー出力に出力されるものを標準出力に流せ,という指示だ.
これだけなら,まあそれほどわかりにくくはない(& の有無など,よくわからないところはあるにしても).
私にとって謎だったのは,上記のリダイレクト指示の順番である.
どうして 2>&1 が先なのか.こちらを先にしてしまったら,1に2の出力も流し込んでしまい,2と1がfile.txtに書き込まれてしまうのではないか.
しかし実際にはそうはならない.
私の思う整合的な理解は以下である.
1および2は,それぞれコマンド出力の番号である.
そして&1および&2は,それぞれ現在(ないしデフォルトで)1および2が割り当てられている出力先である.
つまり1と&1, 2と&2はそれぞれ別のもの(というか,コマンドの結果の出口とそれを表示する先なので,ものごとのカテゴリーが違う)と考える.
で,2>&1という指示は,2の出力を現在の1の出力先である&1に流せ,ということで,つづく1>file.txtは,1をfile.txtに流せ,ということになる.
その結果,2は&1に出て,1はfile.txtに出る,ということになる.
M1 macとIntel macとで設定を共有する場合のhomebrewのパス設定
簡単なメモ.
brewのパスが両者で異なるため,設定を変えないとbrewのフォーミュラ類が利用できなくなる.
if `uname -m` == arm64 then eval "$(/opt/homebrew/bin/brew shellenv)" else eval "$(/usr/local/bin/brew shellenv)" fi
コマンドuname -mを実行すると,チップによって以下のような出力が得られる.
uname -m # arm64 for M1 # x86_64 for Intel
homebrewのパスがM1とIntelで異なるので,それぞれ上記のように記述する.
なおパスはbrewのインストール時に表示されるものを使用する(上記とは限らない).
sshが動かない:Library not loaded
割と毎日のようにsshを使っているが,ある日突然動かなくなり,以下のようなメッセージが出るようになった.
dyld[85860]: Library not loaded: /System/Library/Frameworks/Python.framework/Versions/2.7/Python Referenced from: /usr/local/Cellar/openssh/8.1p1/bin/ssh Reason: tried: '/System/Library/Frameworks/Python.framework/Versions/2.7/Python' (no such file), '/Library/Frameworks/Python.framework/Versions/2.7/Python' (no such file) Abort trap: 6
Python 2.7を呼び出して動かそうとしているが,見つからない,ということらしい.
解決を検索したところ以下のようなものが見つかったが,
Python 2.7は(少なくともHomebrewでは)もうインストールできないので,この方法は使えないし,なにより今更無理やりPython 2.7をもってきて使おうというのがよくない.
とはいえ,基本的な手段を試してみたら解決したので報告する.
$ brew upgrade openssh
opensshではなくシステムのsshを使い続けている場合は,保守性のためにopensshをhomebrewで入れるのがいいかもしれない.
$ brew install openssh
upgradeもinstallも,dependencyがいっぱいあるので時間が結構かかる.
テスタの電池
十年以上前からなんとなく持っているアナログ電気テスタの電池が気づくとすぐ空になっている.最初は抵抗値が検出できず混乱したが,すぐに電気が流れていないと気付いた.しかし減りが早すぎる.どこかショートしてる?
追記
と思ったらヒューズ飛んでた.これはおそらくレンジの設定ミスだと思うが,直接的にはDCmAが250までしかないのに電源モジュールの電流を測ろうとしたときに振り切って飛ばしたのだと思う.いやはや.
Raspberry Pi 4B が起動しなくなる問題
起動しなくなった
sshでRaspberry Piにログインしようとして,IPアドレス,ホスト名の両方を試してもうまくいかない場合,起動していない可能性がある.HDMI 0のポートにディスプレイを繋いだ時,ほぼ正方形の虹色の画面が表示されていてそこから動く気配がない場合,起動に失敗している.いくつか原因があるらしい.
上記の中では,SDカードの異常(破損,規格不足?)が疑われたので,内容を別のカードに移動するか,スクリプトや設定ファイルをサルベージして別のカードにクリーンインストールするかを試みた.
SDカードの中身の移し替え
ラズパイのSDカードを普通にMacに挿しても,Documentフォルダなどがそのまま見られるわけではない.なのでまずはサルベージより中身の移し替えを試みた.
ラズパイのディスクとして使用したSDカードは,いくつかのパーティションに自動で分かれているが,別に異常ではない(参考:Raspberry Pi 4(ラズパイ)起動!虹画面フリーズの原因は意外なものだった… │ きゅうり大爆発).しかし移動するのも,そのままファイルをコピーしたのではダメそうで,dd
コマンドを使って,まずはディスクイメージを作成し,そのディスクイメージを別のSDカードに焼き込んで物理ディスクを作るという流れになる.
ちなみにdiskutil list
でディスクの状態を見ると,ディスクをMacに挿した時にマウントされるbootディスクとRECOVERYディスク以外の空白らしく見えた部分にも,linuxというディスク領域が設定されていることがわかる.つまり名目上は領域の全てを使っていることになっているので,移し替えるディスクは容量が同一でないとダメだと思う(未試行).
/dev/disk3 (external, physical): #: TYPE NAME SIZE IDENTIFIER 0: FDisk_partition_scheme *63.9 GB disk3 1: Windows_FAT_16 RECOVERY 2.6 GB disk3s1 2: Linux 33.6 MB disk3s5 3: Windows_FAT_32 boot 268.4 MB disk3s6 4: Linux 61.0 GB disk3s7
このディスクイメージ作成作業は,上記サイトでは15分ほど要すると書いてあるが,私の環境では,バッファサイズを16mに設定して,ゆうに2時間はかかった.さらにSDカードに焼きこむ作業はその半分くらいの速度しか出ていなかった(健闘した方だと思う).
データのサルベージとクリーンインストール
ディスクの焼きなおしと並行して,とりあえずディスクイメージ作成が終わって解放された旧ディスクからサルベージする方も試みることにした.Macでラズパイのファイルを見るためには,外部ディスクとしてマウントするためにext4fuse
というツールを使う方法があるらしい.
上記サイトにあるようにどちらもHomebrewでインストールする.さて,マウントするのはディスク全体ではなく,そのパーティションごとであるので,上記のdiskutil list
をひとつひとつ試してファイルが入っているところを探し当てる必要がある.結論的には最後のlinuxパーティションが正解.
ファイルを救出したところで,別ディスクにRaspberry Pi OSをクリーンインストールする.まずはsudo diskutil eraseDisk FAT32 NAME MBRFormat /dev/diskN
を実行して,FAT32にフォーマットする(別にDisk Utilityでやっても何の問題もない).
ついでインストール.今回はDisk Imagerをインストールして使ってみたが,これは簡単で便利.リカバリーツールやUbuntuなど他のOSも手軽に扱える.
いつからraspbianという呼び名を使わなくなったのか.つい最近のことのように思うが.
解決(電流不足?)
クリーンインストールはすぐ終わるので,とりあえずそのカードで起動を試みたが,状況は一緒だった.すわ本体の故障かと落胆したが,GPIOに多数の配線が繋がったままだったので,藁にもすがる思いでそれらを外して起動を試みたところ,異常が疑われた旧ディスクで問題なく起動した.
どういうことかよくわからないが,GPIOがいくらか電気をもっていってしまうので,チップに使う電気が足りなくて起動できないということらしい.電気が足りないという問題は,アダプターや電源の問題によっても起きるが,GPIOのせいでも起こることがあるようなので,同様の症状の向きはぜひ試みられたい.ちなみに私のところでは,3V3電源線とGND線だけを外せば起動する.なぜ3V3だけではダメなのかは謎.
もちろんこの時点で,3時間くらい経過して半分弱くらい焼き込みが終わっていたSDカードへのディスク作成は中断した.
残る問題
GPIOに配線を繋いだままでは起動できないのだとすると,なんらかの機器に組み込んで利用する場合,いちいち分解しないと起動できないということになるのでは?
これまでは別に繋いだままでも起動できていたので,たまたま今の配線が悪いということなのか.ちなみにブレッドボードに3色LEDを一本と1KΩ抵抗一本,プルダウン抵抗1KΩのスイッチが6本.なんとなく,スイッチのプルダウン抵抗が悪さをしているような,そうでもないような.
追記
プルダウン抵抗を1kΩから10kΩ,100kΩと変えてみたところ,10kΩでは起動せず,100kΩでは起動した.抵抗を大きくしたことで流れる電流が減ったから?
よくわからないが,GPIOのうちいくつかはデフォルトでいくらか電流が流れるらしく,特に何もしていなくてもLEDがうっすら点いていたりする.おそらくGNDとつながっているとそこで電流が消費されてしまうのだろう.したがって,上では謎だと書いた,3V3だけ外しても起動しないという問題は,3V3ではなく他のGPIOが電流を食っているために起こっている問題だったので当然だったわけである.むしろGNDだけ外せば起動するはず.
オプションの有無で挙動が切り替わるマクロ
TeX言語における条件分岐
TeXには(たぶん)論理式や論理演算子がない(らしい)ので,普通のプログラミング言語と異なる条件分岐の仕方をする.
例えば,ある文字トークンAと文字トークンBが同じである時に挙動Aを行いたい場合には,
\ifx<文字トークンA><文字トークンB><挙動A>
ある数値Aが特定の値より大きい場合に挙動Bを行い,そうでない場合には挙動Cを行いたい場合には,
\ifnum<数値A>><特定の値><挙動B>\else<挙動C>\fi
わかりにくいが,<数値A>
の後の>
は不等号である.
これらは例えば,\ifx
が関数で,第一引数と第二引数を所定の仕方で比較し,所定の関係にあるならば第三引数の処理を実行する,という形式と見ることができる.
このほか,条件として使いたい値などの種類によってさまざまな「ifのようなもの」が用意されていて,使い分けないといけない.
具体例
たとえば,オプション引数をとるマクロにおいて,オプションがある時にはオプションに指定した文字列を表示し,なければ何も表示しないというものを定義する.
環境といいつつ,単に文字列を表示するだけのものである.
\newenvironment{test}[1][]{% \ifx#1\relax \relax \else #1 \fi }{}
なお\newenvironmentにおいて,ふたつめの角括弧にはオプション引数のデフォルト値を指定する(角括弧自体がなければオプションなし).つまり,ふたつめの角括弧をつけることでオプション引数をとる環境を定義できる.
ちなみに\newenvironmentで設定できるオプションは通常はひとつだけ(だと思う).複数指定しようとすると以下のようなエラーが出る.
! You can't use `macro parameter character #' in vertical mode.
このエラーを回避しようとして,単純にvertical modeを脱するだけなら\leavevmode
というプリミティブがあるが,結果は同様(verticalがhorizontalになるだけ)である.オプションを複数指定する仕方はわからない.
Mac OS Mojave以降でのopensslの問題
今更ながらMojaveに更新し,gitをコマンドラインで使おうとしたら下のようなエラーが出た.
$ git pull dyld: Library not loaded: /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib Referenced from: /usr/local/bin/ssh Reason: image not found fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.
解決は以下.
$ brew update && brew upgrade $ brew upgrade openssh
opensslの誤記ではないので念のため.
しかしlaunchdを設定して動かしている自動コミット・プッシュのほうは問題なく動いているので,本質的にはパーミッションの問題らしい.