ひゃまだのblog

ひゃまだ(id:hymd3a)の趣味のブログ

Raspberry Pi(ラズパイ)にプリンタ(Oki c811dn)を設定する

(2024-02-023 初稿 - )

先日、職場でRaspberry Pi(ラズパイ)にプリンタをインストールして欲しいと頼まれた。

最近は、Wi-Fi機能があるプリンタは、Linuxでも簡単に設定できるようになったが、未だに古いプリンタを使っている環境では、まだまだプリンタの設定は面倒で難しいことが多い。

で、頼まれたプリンタの機種は、Oki c811dn で、ラズパイに設定とのことでかなりニッチな情報。

初めは、ラズパイのプリンタドライバを探してみたが、目的プリンタのドライバが見つからず、Webを検索すると以下のページがヒットした。

上記サイトをみると、Oki c811dnは「PCL6エミュレーション」モードが使えるらしく、「Generic PCL 6/PCL XL Printer Foomatic/pxlcolor」のドライバを用いて印刷できたとの記述があった。

筆者のように周りにLinuxユーザが少ない環境にある者にとって、このようなサイトの解決策はとてもありがたい。

ということで、早速、設定して試したところ、無事に設定でき、カラー印刷もできた。

プリンタの設定(ラズパイで撮れなくてごめんなさい)

この記事のままだと、かなりニッチな情報だけとなってしまうが、以下のサイトの「OpenPrintingのPPDを使う」を参照に設定すれば、さらに利用な可能なプリンタが増える可能性があるので、プリンタ設定でお困りなかた試してみて欲しい。

それでは、皆さん、よいLinuxライフを。(^^)/

関連ページ

Bashのwhileとforの無限ループと{}(ブレース)への対応について

(2024-02-11 初稿)

Bashの while と for を利用していて、どうしてそのような仕様になっているのか、不思議なので記事にしてみた。

 

まずは、whileを使った無限ループは、以下のとおり。

なお、無限ループを抜けるのは、Ctrl+c(コントロールとcを同時に押す)で終わってね。

$ while true; do echo "test"; sleep 1; done
test
test
^C

一方、 for を使った無限ループは、以下のとおり。

$ for ((;;)); do echo "test"; sleep 1; done
test
test
^C

while、forともに同様に書ける。

しかし、do doneの代わりに、{}(ブレース)を使った場合は、以下のとおり。

$ while true; { echo "test"; sleep 1; }
> ^C

whileの場合は、文が終了しているとは認識されず、次の文の入力を求められる。

一方、forの場合は、{}(ブレース)を使っても、ちゃんと実行される。

$ for ((;;)) { echo "test"; sleep 1; }
test
test
^C

この違いは何なんだろう?

理由を知っている方は、ぜひ教えてください。

最後に、参考までに、forを使った3回実行する場合は、以下のとおり。

for ((i=0; i<3; ++i)) { echo "test"; sleep 1; }
test
test
test

今回は、whileとforで、なぜ仕様が異なるのか疑問に思っただけの記事だった。^^;

 

関連ページ

Bashの便利なブレース展開(Brace Expansion)

(2024-02-08 初稿 )

 Bashにはブレース展開と呼ばれる便利な機能がある。

このページでは、以下のサイトを参考に作った筆者の備忘録である。

基本編

まずは、ブレース展開の基本的な機能の抜粋について記述する。

echo {a,b,c}   → a b c
echo {a..c}    → a b c
echo {0..4}  → 0 1 2 3 4  # 小さい順
echo {4..0}  → 4 3 2 1 0  # 大きい順

Bash ver4.0 以降は増減を指定できる。

echo {0..4..2} → 0 2 4

ブレース展開は組合せもできる。

筆者は、この組合せを多様するので、本当に助かる。

$ echo {a..b}{0..3} →< a0 a1 a2 a3 b0 b1 b2 b3

前後に文字をつける

$ echo a{b,c,d}e  → abe ace ade

「,」(カンマ)は、前後の文字

$ echo a{,b,c,d}e  → ae abe ace ade

日本語でも可

$ echo 山{,田}の  → 山の 山田の

応用編

深いディレクトリのファイルのバックアップ

$ mv /lpath/longpath/longlongpath/longlonglongpath/config{,.bak}
$ ls lpath/longpath/longlongpath/longlonglongpath/config*
config config.bak

ファイルの一括作成

$ touch test{0..5}
$ ls test*
test0  test1  test2  test3  test4  test5

一括ファイル名変更

$ for f in test*; { mv $f{,.txt}; }
$ ls test*
test0.txt  test1.txt  test2.txt  test3.txt  test4.txt  test5.txt

for文の条件

$ for i in {1..5}; { echo $i; }
1
2
3
4
5

ざっと簡単に紹介したが、本当にbashだけでできることが多くて助かる。

皆さんの少しでも参考になれば幸い。

また、何か気がついたら追記する。

 

関連ページ

 

 

 

Bashのパラメータ展開による大文字、小文字変換

(2024-02-02 初稿 - 2024-02-05 追記)

Bashの文字列演算子については、以前、以下のページに記述した。

先日ネットを検索していたら、Bash 4.0以降のバージョンでは、アルファベット文字の大文字や小文字に変換することができることを知ったので、その方法をメモする。

(2024-02-05 追記)

パラメータ展開による大文字、小文字変換には、@{parameter@operator}tという別のやり方があることがわかったので追記する。

たぶん、こちらの方がわかりやすいと思う。

(追記終了)

 

ちなみに筆者の環境は、以下のとおり。

$ bash --version
GNU bash, バージョン 5.2.15(1)-release (x86_64-pc-linux-gnu)
$ uname -a
Linux fam 6.1.0-17-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.69-1 (2023-12-30) x86_64 GNU/Linux

大文字変換

$ str="abcde"
$ echo ${str^}    → Abcde     # 先頭一文字<
$ echo ${str@u}   → Abcde     #小文字uで先頭文字のみ大文字
$ echo ${str^^}   → ABCDE     # 全文字
$ echo ${str@U}   → ABCDE     #大文字Uで全文字 
$ str="abcdeabcde"
$ echo ${str^^[a-c]}  → ABCdeABCde  # aからcまで
$ echo ${str^^[ad]}  → AbcDeAbcDe   # aとdのみ

なんと、bashだけでなんでもできそう。

小文字変換

続いて、小文字変換

$ str=ABCDE"
$ echo ${str,} → aBCDE   # 先頭一文字
$ echo ${str,,} → abcde  # 全文字
$ echo ${str@L} → abcde  # 全文字小文字
$ str=ABCDEABCDE"
$ echo ${str,,[A-C]} → abcDEabcDE  # AからCまで
$echo ${str,,[AD]}   → aBCdEaBCdE  # AとDのみ

(2024-02-05追記)

@{parameter@operator}には、いろいろ便利な記述があるので、ここで一覧で示す。

$ str="abcde"
$ echo ${str@U} → ABCDE     #大文字Uで全文字
$ echo ${str@u}  → Abcde    #小文字uで先頭文字のみ大文字
$ str="ABCDE"
$ echo ${str@L} → abcde     # 全文字小文字
$ str="ABC DEF"
$ echo ${str@Q} → 'ABC DEF' # 空白文字もクォート
$ str="ABC\tDEF\n
$ echo ${str@E}  → ABC DEF  # エスケープ文字を展開
$ str="\V \t"
$ echo ${str@P} → 5.2.15 19:40:33  # プロンプトの文字も解釈して展開
$ str=("abc" "def" "hij")
$ echo ${str[@]@K} → 0 "abc" 1 "def" 2 "ghi"  # 配列を連想配列に
$ declare -A ass=([key1]="abc" [key2]="def" [key3]="ghi")
$ echo ${ass[@]@K} → key2 "def" key3 "ghi" key1 "abc"  # 連想配列を展開
$ str=("abc" "def" "hij")
$ echo ${str[@]@U} → ABC DEF HIJ  # 配列の要素を大文字に
$ echo ${str[*]@U} → ABC DEF HIJ    # 同上
$ echo ${ass[@]@U} → DEF GHI ABC  # 連想配列の値を大文字に
$ echo ${ass[*]@U} → DEF GHI ABC     # 同上

(追記終了)

なんと、便利なこと。sedを呼ぶ機会が減りそうだ。

関連ページ

Raspberry Pi 3B+ に sonic-pi をインストールしてみた

(2024-02-01 初稿 - 2024-02-02 追記)

はじめに

最近、自分で動画を作成してみようかと思っている。しかし、BGMのない動画はやや寂しいので、これまた自分で簡単な曲を作ってみようと思っている。

筆者は、Debianを使っているので、楽曲を作るソフトウェアといえば、sonic-pi または rosegarden くらいしか知らない。どなたか、Linux環境でも良いDTMを紹介してください。m(_ _)m

このページでは、久しぶりにRaspberry Piにsonic-piをインストールして、使ってみたので、そのメモを残す。

最初に言っておくが、Raspberry Pi 4 ではsonic-piをインストールできたが、音を鳴らすことができなかった。もしかしたら、筆者がBluetoothのスピーカーを利用していることが原因かもしれない。

いずれにしても、Raspberry Pi OS 12(bookwarm) は pulseaudioとpipewireへの過渡期にあるようで、少なくともBluetoothスピーカーにつないだRaspberry Pi 4にインストールすることはあきらめた。

ちなみに、sonic-piはリアルタイムに演奏するためにjackを利用するが、jackはひとつのプログラムで専有されやすいようで、マルチユーザー環境では利用が難しいようである。そこで、pipewireがこれらの問題を解決するために開発されたようだが、前述のとおり、Raspberry pi OSではちょうど過渡期のようで、うまく動作させられなかった。

そこで、デフォルトではWaylandやpipewireがインストールされない余っていたRaspberry Pi 3B+にsonic-piをインストールして、HDMIでディスプレイ兼スピーカーに接続して使ってみたところ、うまく動作させることができた。以下の記述は、このような環境におけるものである。

筆者の環境

念の為に、筆者の環境を示す。

$ cat /etc/debian_version
11.8
$ uname -a
Linux rp32 6.1.21-v7+ #1642 SMP Mon Apr  3 17:20:52 BST 2023 armv7l GNU/Linux

sonic-pi のインストール

sonic-piのパッケージは、Raspberry Pi OSにあるので、インストールは以下のとおり。

$ sudo apt install sonic-pi

ちなみに、インストールしたsonic-piのバージョンは、3.2.2。

注意点として、インストールの途中で、jackを利用するので、マルチユーザにはおすすめできないが、変更をするか?と聞かれる(うろ覚えで申し訳ない)。デフォルトでは「いいえ」が選択されているが、「はい」を選択して変更をしないとうまく音が出ない。

起動中のSonic-pi

筆者は、とても作曲について記述するほどの技量を持ち合わせていないので、以下にリンクを掲載するので、具体的な方法は以下で学んで欲しい。

大変驚いたことに、以下のサイトにギターのTABをそのまま演奏するコードが載っており、実際に動作できることを確認した。

もちろん、TABを貼り付けた後にいろいろと加工しないと行けないが、かなり効率的に楽曲をつくることができることは間違いがなく、sonic-piがrubyをベースとするデジタルプログラミングシンセサイザーであるメリットだ。

上記、サイトから引用させていただくと、コードは以下のとおり。以下のコードは、Led Zeppelinの「Stairway to Heaven」。

t0=
"e-------5-7-----7-8-----8-2-----2-0---------0---------------------
b-----5-----5-------5-------3-------1---1-----1-------------------
g---5---------5-------5-------2-------2---------2-0-2-2-----------
-7-------6-------5-------4-------3-------------------------------
a-------------------------------------------------2-0-0---0--/8-7-
e-----------------------------------------------------------------"
t=t0.split("\n").reject(&:empty?)
tuning=[:E3,:A3,:D4,:G4,:B4,:E5].reverse
for i in 0...t.length/6
  for j in 1...t[i].length
    for k in 0...6
      case t[i*6+k][j]
        when "0","1","2","3","4","5","6","7","8","9"
        play tuning[k]+t[i*6+k][j].to_i
      end
    end
  sleep 0.15
  end
end

(2024-02-02 追記)

ちなみに、ここでは、紹介しないが、ChatGPT等の生成AIを利用すれば、簡単に曲を作ってもらえる。

(追記終了)

おわりに

何か良いBGMができたら、こちらで紹介しようと思っているが、いつのことやら… (^^ゞ

関連ページ

Shellcheckを使ってBashスクリプトのチェックと最適化

(2023-01-29 初稿 )

はじめに

筆者は、Bashスクリプトをよく利用しているが、その独自の記述方法のためにエラーが起きたり、思いどおりに動作させられないことがしばしばある。

最近、ネットで shellcheck のことを知り、シェルスクリプトの強力な助っ人になりそうなことがわかった。本記事では、ShellCheckの主な機能とインストールと簡単な使い方を紹介する。

 ShellCheckとは

ホームページによれば、初心者から上級者までのレベルに応じたコード品質やバグの指摘を目的とするツール。オープンソースで無料であるため、shellのlintとしては、最も人気がある。

筆者は、主にシンタックスの確認、コードの最適化のために用いようと思っている。

インストールと使い方

インストール

ShellCheckのインストールは、Debian/Ubuntuであれば、以下のとおり簡単にインストールできる。

$ sudo apt-get install shellcheck

使い方

以下のように、shellスクリプトをチェックすることができる。

$ shellcheck your_script.sh

エラーの検索と対策

例えば、複数のエラーを含む以下のスクリプトを作成する。

#!/usr/bin/bash
num=2
[[ $# -ne $num ]] && {echo "error"; exit}

上記スクリプトを、shellcheckすると以下のようにエラーコードが示される。

$ shellcheck example 
In example line 4:
[[ $# -ne $num ]] && {echo "error"; exit}
                     ^-- SC1073 (error): Couldn't parse this brace group. Fix to allow more checks.
                      ^-- SC1054 (error): You need a space after the '{'.
                                        ^-- SC1083 (warning): This } is literal. Check expression (missing ;/\n?) or quote it.

In example line 5:
^-- SC1056 (error): Expected a '}'. If you have one, try a ; or \n in front of it.
^-- SC1072 (error): Missing '}'. Fix any mentioned problems and try again.

For more information:
  https://www.shellcheck.net/wiki/SC1054 -- You need a space after the '{'.
  https://www.shellcheck.net/wiki/SC1056 -- Expected a '}'. If you have one, ...
  https://www.shellcheck.net/wiki/SC1083 -- This } is literal. Check expressi...

今回のエラーは、{}の前後のspaceが足りないのと、{}内の「;(セミコロン)」が足りないだけなので、エラーの原因は調べるまでもないが、上記に記述があるとおり、例えば  https://www.shellcheck.net/wiki/SC1056 をネットで検索すると、原因とその対策まで示してくれる。

エラーの検索

対策まで示してくれるから、とっても便利。

念の為に書くが、以下のように修正すれば、エラーが出なくて正常動作する。

[[ $# -ne $num ]] && { echo "error"; exit; }

この他、-i や -e オプションを付けることによって、以下のことができる。

  • -i オプション: みたいエラーコードを指定する。
  • -e オプション: あまりにたくさんのエラーが出るときに、指定するエラー出力を除く

おわりに

ShellCheckはshellスクリプト開発者の頼りになるツールで、お役に立つことができると思われる。筆者も、これから自分のshellスクリプトをcheckして、できるだけ有益なスクリプトを作りたいなぁ…(希望的観察)。

関連ページ

DockerのDockerfileとrun、execのオプションの便利技

(2024-01-23 初稿 - )

はじめに

Dockerを使い始めて1年以上になるのに、人様の作ったDokerfileやrun、execのオプションを見て、なるほどと感心することばかり。何か新しいことをやろうとする度に、新しいオプションや発見がある感じ。

しかし、残念なことに筆者はすぐに忘れてしまうので、ここにメモを残す。

なお、このページはDockerの網羅的なマニュアルでは無く、筆者が躓いたり、便利だと思ったオプションのみを記述しているのであしからず。

Dockerfileのオプション

ENV DEBIAN_FRONTEND noninteractive

Dockerfile内でapt-get install しようとすると、対話的なインストールが必要なパッケージの場合はうまくインストールできない。

筆者が経験したパッケージは、libgl1-mesa-dev 等でタイムゾーンを聞かれるので、インストールが途中で止まってしまう。

そんなときは、ENV DEBIAN_FRONTEND noninteractive オプションを付ければよいのだが、docker内の環境だとしても、この環境変数を安易に全体につけるべきではないとのこと。具体的には、以下のサイトを参照のこと。

具体的には、対話的なパッケージのインストールが必要な部分のみ以下のようにインストールすることにした。

RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y libgl1-mesa-dev 

Runのオプション

終了後に削除( --rm)

コンテナからExitし、利用したコンテナが不要の場合は --rm オプションを付けることにより、終了後に削除してくれる。

本オプションがない場合は、docker ps -a で全てのコンテナを表示させ、目的のコンテナを docker rm コンテナ名(or ID)で削除する必要がある。

ちなみに、コンテナの削除に時間が掛かるが、docker rm -f コンテナ名(or ID)とすると、即座に削除できる。

コンテナの名前 --name hogehoge

長く利用するコンテナや似た機能で少しずつ異なるコンテナを作成する場合は、自分で名前を付けた方が、管理しやすくなる。

--name hogehoge

現在のディレクトリの共有 -v $PWD:/work 

コンテナ内にスクリプトやデータを多数引き渡す必要がある場合は、あるディレクトリにまとめて保存しておき、コンテナをrunするときにディレクトリごと引き渡す方法が効率的だ。

筆者は、tensoroflowやWebサーバ関連のスクリプト等を保存するディレクトリを決めた後、そのディレクトリをカレントディレクトリにしてから、runコマンドで起動している。このためのオプションは、以下のとおりになる。

-v $PWD:/work

コンテナ内では、/work(任意の名前で良い)にアクセスすれば、必要なスクリプトやデータを利用することができる。

フォントの共有 -v /usr/share/fonts:/usr/share/fonts

筆者は、まだ困ったことは無いが、コンテナ内のフォントが不足して表示が□(トーフ)になってしまうことがある。

様々なフォントをコンテナ内にインストールするのは無駄なので、ホスト側にあるフォンを共有することにより、フォントのトラブルを回避することができる。

-v /usr/share/fonts:/usr/share/fonts

ディスプレイの共有 -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix

コンテナ内でGUI表示をするプログラムを利用する場合は、ディスプレイを共有する必要がある。そのためのオプションは、以下のとおり。

-e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix

なお、ホスト側では、忘れずに xhost + する必要がある。

$ xhost +

本来であれば、上記サイトにあるとおり、以下のように起動するコンテナのみに限定するように許可することが望ましい。

$ xhost +local:$(docker inspect --format='{{ .Config.Hostname }}' [コンテナID])

/etc/hostsへのホストの追加

ごく少数のホストを /etc/hosts に追加するオプションは以下のとおり。

ホストの追加 少ない場合

--add-host=fuga:192.168.xxx.xxx

ただし、追加するホストが多い場合は、予めカレントディレクトリに hosts ファイルを作成しておき、以下のとおり共有する方法が簡単である。

ホストの追加 多い場合

-v ./hosts:/etc/hosts

なお、ホスト側の ./ は必要なので付け忘れないように。

ユーザ、グループの共有 -u $(id -u):$(id -g) 

rootlessモードやコンテナ内にホストのユーザーを引き継ぐには、以下のオプションを付加する。

-u $(id -u):$(id -g) 

ただし、idが引き継がれる名無しさんになってしまうので、ユーザ名やグループ名も引き継ぐ場合は、以下のとおりホスト側のpsswdとgroupsファイルを共有する。

-v /etc/passwd:/etc/passwd:ro
-v /etc/group:/etc/group:ro

また、万が一の書き換えに備えて :ro リードオンリーオプションも併せて付加すると良い。

メモリの追加  --shm-size=2gb  

yolov5で物体検出を行ったときに、メモリ不足でプログラムが途中で終了してしまった。調べると、Dockerはデフォルトでは 16MB のメモリで起動するようである。

そのようなときには、メモリ余裕を持たせて起動する。

--shm-size=2gb

execのオプション

ログインシェルの実行 --login

Dockerで、execのオプションは、あまり使ったことがない。

以前、コンテナ内の .profile にpathの設定を追加して、コンテナを起動したが、一向にpathが追加されない。

調べてみると、execで起動する際に、 --login オプションを追加することで、.profileを実行してくれて、pathもめでたく設定された。

exec コンテナ名 --login

おわりに

以上、筆者が使ってみて便利だと思ったDockerのオプションをメモしてみた。

また、何か気がついたら追記する。 

関連ページ