繰り返し文字生成の実行時間

2024/08/31 19:08 OS別::Linuxその他::シェル
bash で Separator のような、任意の文字を繰り返し出力する方法を探して、見つけたこちら。
https://genzouw.com/entry/2020/10/29/211143/2094/

選択肢が割とあって「お、おう……」となったので「実行速度」で選ぶことにした記事。
シェルスクリプトなので、普段は実行時間なんて気にしないのだけど。

ここで結論を先に書いておくと、ビルトインコマンドである for 文(for *1; do echo -n '='; done)を利用するのが最強のようです。
次点で、print (printf "=%0.s" 0..9)でした。

*1 : i=0; i<10; i++

テスト環境

テスト環境は、以下のような状況です。
$ uname -moi
armv7l unknown GNU/Linux
$
$ bash -version | head -n 1
GNU bash, バージョン 5.1.4(1)-release (arm-unknown-linux-gnueabihf)
$
$ . /etc/os-release
$ echo ${PRETTY_NAME}
Raspbian GNU/Linux 11 (bullseye)

テスト方法

スクリプトにしておいて、シンプルに time で計測します。

作成したスクリプトおよび内容は、以下の通りです。
$ ls -1
test-A.sh
test-B.sh
test-C.sh
test-D.sh
test-E.sh
test-F.sh
test-G.sh
work.sh
$
$ for i in *.sh
do
  echo "### ${i}"
  echo "----------------------------------------------------"
  cat ${i}
  echo "----------------------------------------------------"
  echo ""
done
### test-A.sh
----------------------------------------------------
#!/bin/bash
printf "=%0.s" {0..9}
----------------------------------------------------

### test-B.sh
----------------------------------------------------
#!/bin/bash
yes = | head -n 10 | tr -d '\n'
----------------------------------------------------

### test-C.sh
----------------------------------------------------
#!/bin/bash
seq -s '=' 0 10 | tr -d '[0-9]'
----------------------------------------------------

### test-D.sh
----------------------------------------------------
#!/bin/bash
seq -s '=' 0 10 | sed "s/[0-9]//g"
----------------------------------------------------

### test-E.sh
----------------------------------------------------
#!/bin/bash
for ((i=0; i<10; i++)); do echo -n '='; done
----------------------------------------------------

### test-F.sh
----------------------------------------------------
#!/bin/bash
seq 10 | xargs -i echo -n =
----------------------------------------------------

### test-G.sh
----------------------------------------------------
#!/bin/bash
seq 10 | xargs -i printf "="
----------------------------------------------------

### work.sh
----------------------------------------------------
#!/bin/bash

fnChecker() {
  echo "### ${1}"
  time ./${1}
}

fnChecker test-A.sh
fnChecker test-B.sh
fnChecker test-C.sh
fnChecker test-D.sh
fnChecker test-E.sh
fnChecker test-F.sh
fnChecker test-G.sh
----------------------------------------------------

$

計測

傾向が見えればよいと考えたため、とりあえず1回実行したところが、以下の数値です。
$ ./work.sh
### test-A.sh
==========
real    0m0.016s
user    0m0.013s
sys     0m0.003s
### test-B.sh
==========
real    0m0.028s
user    0m0.020s
sys     0m0.030s
### test-C.sh
==========

real    0m0.023s
user    0m0.024s
sys     0m0.007s
### test-D.sh
==========

real    0m0.028s
user    0m0.009s
sys     0m0.028s
### test-E.sh
==========
real    0m0.014s
user    0m0.001s
sys     0m0.013s
### test-F.sh
==========
real    0m0.082s
user    0m0.026s
sys     0m0.067s
### test-G.sh
==========
real    0m0.080s
user    0m0.036s
sys     0m0.051s
$

結論

for コマンドを使います。

感想

printf コマンド(test-A.sh)もなかなか良い数字なんだけど、ビルトインコマンドの for によるループ(test-E.sh)が強いですね。

その他、普通は bash の予約語なので利用されない time コマンドを使ってみての計測なんかもしてみましたが、メモリ使用率なんかは変化が少ないようです。

wait

time コマンドで計測できる wait の内容は、次の通り(man bash の引用)。
wait の回数、つまりそのプログラムが自発的にコンテキストスイッチされた回数。
例えば、I/O 操作の完了を待っている間などが該当する。
$ type time
time はシェルの予約語です
$
$ which time
/usr/bin/time
$
$ for i in test-*.sh
> do
>    /usr/bin/time -f "\nwait: %w" ./${i}
> done
==========
wait: 1
==========
wait: 8
==========

wait: 7
==========

wait: 5
==========
wait: 1
==========
wait: 31
==========
wait: 36
$
計測した結果は上記の通りですが、printf と for でのループ、待ちなんてほとんど発生してませんね。

その他

あと、こんな感じで他にもいろいろ計測できたりします。

これは、メモリ(プロセス生存中のそのプロセスの resident set size の最大値)。
$ for i in test-*.sh
do
   echo "### ${i}"
   /usr/bin/time -f "\n Memory: %MKB" ./${i}
done
### test-A.sh
==========
 Memory: 2752KB
### test-B.sh
==========
 Memory: 2820KB
### test-C.sh
==========

 Memory: 2820KB
### test-D.sh
==========

 Memory: 2816KB
### test-E.sh
==========
 Memory: 2692KB
### test-F.sh
==========
 Memory: 2868KB
### test-G.sh
==========
 Memory: 2868KB
$
うん。だいたい 3MB 程度ですね。

メジャーページフォルトの回数

外部コマンドでは、メジャーページフォルトの回数を計測も出来たりします。
$ for i in test-*.sh
do
   echo "### ${i}"
   /usr/bin/time -f "\n Page: %F" ./${i}
done
有意な差がないので結果は載せないですが、test-C.sh (seq -s '=' 0 10 | tr -d '[0-9]') はちょこちょこページフォルトが発生している模様。
他のも、合ったりなかったり。
$ for i in test-*.sh
do
   echo "### ${i}"
   /usr/bin/time -f "\n Memory: %MKB" ./${i}
done

RPi - LBP221 設定

2023/12/19 12:23 OS別::Linuxその他::デバイス
Raspberry Pi OS で、ネットワークプリンタ LBP221 の設定を行います。

環境

対象機器

今回使用した機器は、次の通りです。
種類機器備考
設定対象サーバRaspberry Pi 3 Model BRaspbian GNU/Linux 11 (bullseye)
プリンタCanon LBP221モノクロレーザープリンタ

DNS 設定

次の名前解決設定を行っています。
項目設定備考
正引き192.168.1.20 lbp221.example.jpドメインは省略して利用
以下の手順でドメイン部分は、Linux 環境において /etc/resolv.conf で補完する domain 設定を行っており、省略しています。
また、Windows 環境でも hosts に記述しているため、筆者の環境ではどの端末でも上記名称のまま接続できるようになっています。
$ ping -4c1 lbp221
PING lbp221.example.jp (192.168.1.20) 56(84) bytes of data.
64 bytes from 192.168.1.20 (192.168.1.20): icmp_seq=1 ttl=64 time=0.349 ms

--- lbp221.example.jp ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.349/0.349/0.349/0.000 ms

ドライバ

Canon 公式サイトで LBP221 のプリンタドライバが提供されていますが、Raspberry Pi の CPU には対応していません。
上記サイトを見る限り、動作確認済み OS に、Debian 11.5(Intel/AMD 32bit/64bit、ARM 64bit)が存在します。
Raspberry Pi OS は ARM になるのでプリントできそうに思えますが、標準で提供されるインストーラーではエラー終了します。

ここでは CUPS 開発者が推奨していることもあり、ドライバーレス印刷を行います。

なお、プリンタが次のいずれかの標準に対応していれば、ドライバーレス印刷が可能になります。
AirPrint™
IPP Everywhere™
Mopria®
Wi-Fi Direct Print Services

プリンタ設定

IP アドレス設定

LBP221 はネットワークに対応しているので IPv4 アドレスを設定します。
詳細については、付属のマニュアルを参照してください。

ビジネス用途のプリンタだけあって、パスワード設定なども行います。

Wi-Fi にも対応していますが、設定時に接続できなかった*1ため LAN ケーブルを使っています。

Web UI 確認

プリンタの Web UI にアクセスしてみます。
http://lbp221.example.jp/
表示されれば、プリンタが正常にネットワーク接続されていることが確認できます。
なお、管理者モードでログインするには、任意で設定したパスワードが必要です。

*1 : いろいろ原因を探ったところ、タイミング悪く Wi-Fi 機器が故障していました。

Raspberry Pi OS 設定

パッケージインストール

Raspberry Pi OS に、印刷に必要なパッケージをインストールします。
$ sudo apt install cups system-config-printer

プリンタ接続確認

ipptool で確認したところ [PASS] が表示されているので LBP221 は ipp に対応しています。
$ ipptool -tv ipp://lbp221:631/ipp/print get-printer-attributes.test | grep get-printer-attributes
"/usr/share/cups/ipptool/get-printer-attributes.test":
    Get printer attributes using get-printer-attributes                  [PASS]
なお、LBP221 はモノクロレーザープリンタなので確認しませんでしたが、カラープリンタの場合は "image/jpeg" が含まれていることも確認します。

CUPS 設定

ドライバーレス印刷に対応しているので、lpadmin コマンドを使用して CUPS に登録します。
$ lpadmin -p LBP221 -E -v ipp://lbp221/ipp/print -m everywhere
$ lpstat -p
プリンター LBP221 は待機中です。2023年12月18日 11時08分09秒 以来有効です
オプション -p に指定するプリンタ名は、以後の印刷操作で使用するものなので、IP アドレスと紐づかなくても問題ありません。
また、-v オプションに使用するドメイン名も、IP アドレスで問題ありません。
環境に合わせて、適切に読み替えてください。

テスト印刷

CUPS に用意されているテストページを印刷してみます。
$ lp -d LBP221 /usr/share/cups/data/default-testpage.pdf
Raspberry Pi OS の場合、debian で用意されたテストページが印刷されます。

その他

更新履歴

  • 2023.12.19 使用していた jimba.jp ドメインを、例示用のドメインとして example.jp へ変更。

adiary 関連ライブラリ

2023/12/14 15:35 OS別::Linuxその他::技術情報
Raspberry Pi を利用したウェブサーバで adiary を利用する際、あると便利なライブラリが存在します。
そのライブラリに関連するパッケージをインストールします。

対象は、Raspbian GNU/Linux 12 (bookworm) になります。

必須パッケージ

adiary の動作に必要なパッケージをインストールします。
$ sudo apt install perl

指定ライブラリ

adiary を便利に使うために adiary が指定するライブラリをパッケージでインストールします。

Image::Magick (PerlMagic)

存在すれば adiary 内で画像縮小が可能です。
$ sudo apt install perlmagick

Net::SSLeay

外部サイトへの https 通信に必要です。
$ sudo apt install libnet-https-any-perl

CryptX

adiary の push 通知プラグインで使用します。
$ sudo apt install libcryptx-perl

目的によるインストール

当手順では使用しませんが、必要があれば利用することになるためインストール手順を記載します。

git

公式サイトから git でインストールする際に利用します。
$ type git > /dev/null 2>&1 || sudo apt install git

確認方法

パッケージ

$ sudo apt list perl

ライブラリ

$ sudo apt list perlmagick libnet-https-any-perl libcryptx-perl

git

$ sudo apt list git

apache2 設定

2023/12/14 15:04 OS別::Linuxその他::技術情報
Raspberry Pi を利用したウェブサーバに、Apache2 およびモジュールをインストールします。
対象は、Raspbian GNU/Linux 12 (bookworm) になります。

apache2 インストール

パッケージインストール

Debian 系の Apache パッケージ名は apache2 になります。
apache2 のインストール有無を確認して、インストールを実行します。
$ sudo apt list apache2
$ sudo apt -y install apache2 apache2-doc
$ sudo apt -y autoremove

Apache2 バージョン情報非表示

必要に応じて apache2 のバージョン情報を非表示にします。
$ grep -i includeoptional /etc/apache2/apache2.conf
IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf
IncludeOptional conf-enabled/*.conf
IncludeOptional sites-enabled/*.conf
$ cd /etc/apache2/conf-available
$ sudo cp -p security.conf{,_$(date +%Y%m%d)}
$ sudo vi security.conf
(書き換え)
$ sudo diff security.conf{,_$(date +%Y%m%d)}
25c25
< #ServerTokens OS
---
> ServerTokens OS
27d26
< ServerTokens Prod
36,37c35,36
< ServerSignature Off
< #ServerSignature On
---
> #ServerSignature Off
> ServerSignature On
$

Apache2 設定反映

$ sudo apachectl configtest
$ sudo systemctl reload apache2
configtest メッセージ
以下のメッセージが表示されることがあります。
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
fully qualified domain name (FQDN) が特定できない、というメッセージなので、特定する設定を入れてあげます。
いくつか方法はあるのですが、ここではシンプルな力技でいきます。
$ sudo vi /etc/apache2/conf-available/fqdn.conf
$ cat /etc/apache2/conf-available/fqdn.conf
ServerName example.jp
$ sudo a2enconf

apache2 モジュールインストール

apache2 を入れた後、必要に応じてモジュールも追加インストールする必要があります。
以下のモジュールを追加インストールします。
項目説明備考
cgidcgi を作動させるためのモジュール
RewriteEngineRewrite Engine を利用するためのモジュール
remoteipログの出力先変更等で IP アドレスを利用するためのモジュール

cgid

モジュール確認
モジュールがインストールされていることを確認します。
$ a2query -m cgid
cgid (enabled by site administrator)
デフォルトで有効化されるはずですが、モジュールがインストールされていなければ a2enmod で cgid を有効にします。
モジュールの有効化
モジュールを有効化します。
$ sudo a2enmod cgid
Module cgid already enabled

RewriteEngine

モジュール確認
モジュールがインストールされていることを確認します。
$ a2query -m rewrite
rewrite (enabled by site administrator)
モジュールがインストールされていなければ a2enmod で rewrite を有効にします。
モジュールの有効化
モジュールを有効化します。
$ sudo a2enmod rewrite
Module rewrite already enabled

remoteip

モジュール確認
モジュールがインストールされていることを確認します。
$ a2query -m remoteip
remoteip (enabled by site administrator)
モジュールがインストールされていなければ a2enmod で rewrite を有効にします。
モジュールの有効化
モジュールを有効化します。
$ sudo a2enmod remoteip
Module remoteip already enabled

モジュール設定の有効化

$ sudo apachectl configtest
$ sudo systemctl reload apache2

RPi OS NTP 設定

2024/06/22 19:38 OS別::Linuxその他::技術情報
Raspberry Pi を利用したサーバの、初期に行うべき手順で NTP を設定します。
対象は、Raspbian GNU/Linux 12 (bookworm) になります。

パッケージ

インストール

パッケージのインストール状況を確認して、必要であればインストールします。
$ sudo apt list ntpsec ntpdate dnsutils
$ sudo apt install ntpsec ntp-doc ntpdate dnsutils

名前解決確認

名前解決ができることを確認します。
$ dig ntp.nict.jp +short

NTP 設定

設定差分の読み替え設定

$ . /etc/os-release
$ pNtpConfDir="/etc/ntpsec/ntp.conf"

設定ファイル修正

$ sudo cp -p ${pNtpConf}{,_$(date +%Y%m%d)}
$ sudo diff ${pNtpConf}{,_$(date +%Y%m%d)}
$ sudo vi ${pNtpConf}
---------------------------------------------------------
(pool をコメントアウトして、serverに ntp.nict.jp を指定する)
---------------------------------------------------------
$ sudo diff ${pNtpConf}{,_$(date +%Y%m%d)}
20c20
< #tos maxclock 11
---
> tos maxclock 11
34,38c34,37
< #pool 0.debian.pool.ntp.org iburst
< #pool 1.debian.pool.ntp.org iburst
< #pool 2.debian.pool.ntp.org iburst
< #pool 3.debian.pool.ntp.org iburst
< pool ntp.nict.jp iburst
---
> pool 0.debian.pool.ntp.org iburst
> pool 1.debian.pool.ntp.org iburst
> pool 2.debian.pool.ntp.org iburst
> pool 3.debian.pool.ntp.org iburst
52c51
< #restrict ::1
---
> restrict ::1

設定の反映

$ sudo systemctl status ntpsec
$ sudo systemctl stop ntpsec
$ sudo ntpdate ntp.nict.jp
$ sudo systemctl start ntpsec
$ sudo systemctl status ntpsec
もし status 確認で次のようなエラーが出力されていたら、ディレクトリを作成する。
11月 05 11:01:02 rasp012 ntpd[1385]: statistics directory /var/log/ntpsec/ does not exist or is unwriteable, error No such fi>
$ grep ntp /etc/passwd
ntpsec:x:112:122::/nonexistent:/usr/sbin/nologin
$ sudo mkdir /var/log/ntpsec
$ sudo chown 112:122 /var/log/ntpsec
$ ls -ld /var/log/ntpsec
drwxr-xr-x 2 ntpsec ntpsec 4096 11月  5 11:02 /var/log/ntpsec
$ sudo systemctl status ntp
$ sudo systemctl restart ntp
$ sudo systemctl status ntp
$ ls -l /var/log/ntpsec

設定反映確認

$ ntpq -p
     remote                                   refid      st t when poll reach   delay   offset   jitter
=======================================================================================================
 ntp.nict.jp                             .POOL.          16 p    -  256    0   0.0000   0.0000   0.0010
*ntp-a2.nict.go.jp                       .NICT.           1 u    -   64  377   4.4718   1.3757   3.6481
-ntp-b2.nict.go.jp                       .NICT.           1 u   13   64  377   5.0246   1.0815   3.5915
+ntp-a3.nict.go.jp                       .NICT.           1 u    1   64  377   4.9172   1.4364   3.4305
+ntp-k1.nict.jp                          .NICT.           1 u    2   64  377  16.5057   0.5122   3.4384
+ntp-b3.nict.go.jp                       .NICT.           1 u    -   64  377   4.5500   5.6319   4.4448
 ntp-a3.nict.go.jp                       .INIT.          16 u    -  128    0   0.0000   0.0000   0.0010
 2001:ce8:78::2                          .INIT.          16 u    -  128    0   0.0000   0.0000   0.0010
 ntp-a2.nict.go.jp                       .INIT.          16 u    -  128    0   0.0000   0.0000   0.0010
ntp は、ホスト名に * が付いているサーバに同期している。
また、IPアドレスで確認したい場合は、オプションに -n を追加して ntpq -np 等とする。

その他

NTP サーバとして利用するなら追加設定が必要なので、別途 NTP サーバとしての設定を行う。
例えば、次のような認証を行う。
restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap

更新履歴

日付内容
2024.6.19Linux 12 (bookworm) 用に設定内容を変更した*1

*1 : Raspbian GNU/Linux 11 (bullseye) と Raspbian GNU/Linux 12 (bookworm) では、設定ファイルだけではなく、設定内容も微妙に変更が必要で同期しなかったため。