UNIXやLinuxの最近のブログ記事

もう一ヶ月くらい前から、お客さんから異変の連絡は届いていた。

「当社Webの新着情報の X への自動投稿がされていない」
「Web から業務スケジュールの CSV ファイルをアップロードしたのに、それがDBに反映していない」
などだ。

どれも、Web画面での操作でサーバ上にファイルが作成される。それを cron で実行される監視プログラムで数分おきにポーリングし、ファイルが作成されているのが確認できたらバッチ処理を実行。そのファイルの内容を X に投稿したり、DBに登録したりしている。

お客さんから連絡を受けたらプログラムなど調べてみるのだが異常は見つからず、手動で実行したら正常に処理されるので「原因不明だが、とりあえず動いたのでOK」的に有耶無耶になっていたのである。

今夜もそういう連絡があったので、ついに俺も「ちゃんと調べてみるか」と重い腰を上げ(^^;、Qiita に @nagimaruxxx(Nagimaru)さんが投稿されていた「cronがどうやっても動かない時に考えられる原因とその対処法」という記事の「1. そもそもcronが動いてない」を試してみたら、

# service crond status
Redirecting to /bin/systemctl status crond.service
??rond.service - Command Scheduler
   Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Mon 2026-03-09 21:46:17 JST; 1 months 14 days ago
  Process: 1370 ExecStart=/usr/sbin/crond -n $CRONDARGS (code=exited, status=0/SUCCESS)
 Main PID: 1370 (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/crond.service

Active が inactive (dead) になってるやん。3/9 に落ちてるやん。丁度「X の投稿がされない」という連絡が来たのが 3/10 である。どんぴしゃじゃん。

すぐに実行。

# service crond start
Redirecting to /bin/systemctl start crond.service
# service crond status
Redirecting to /bin/systemctl status crond.service
??rond.service - Command Scheduler
   Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2026-04-23 22:00:05 JST; 6s ago
 Main PID: 15601 (crond)
   CGroup: /system.slice/crond.service
           ??15601 /usr/sbin/crond -n

Apr 23 22:00:05 hoge systemd[1]: Started Command Scheduler.
Apr 23 22:00:05 hoge crond[15601]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 54% if used.)
Apr 23 22:00:05 hoge crond[15601]: (CRON) INFO (running with inotify support)
Apr 23 22:00:05 hoge crond[15601]: (CRON) INFO (@reboot jobs will be run at computer's startup.)

これで、監視プログラムがちゃんと作動するのを確認。プログラムばかり調べていたけど、crond が落ちてただけかい!!

いや、皆さんの中には、「そんなんすぐ気づくやろ」「一ヶ月もほってたとはどういうことだ」と怒られる方もいらっしゃるでしょう。

原因は二つかな。まず、俺が UNIX ライクな OS を触るようになってもう 30年以上経つが、「crond が落ちてた経験が一度もない」ってこと。httpd、sshd、named などのデーモンがこけたことは何度もあるが、crond は今回が初体験。なので crond が落ちてるなんて発想がなかったわ(笑)

そして二つ目が、「そもそもこのサーバ、俺が管理してるわけじゃない」ってことやね。俺がこの約二十年間に作ったプログラムが大量に動いているので root 権限を持たせてもらっているが、運用管理はやってないのよね。だからプログラムの調査はするけど、サーバ環境をそんなに力を入れて調べることは通常ないのであ~る。

というか、プログラムの保守契約もしていない。瑕疵担保責任ももう時効のプログラムばかりで、調査をしていること自体、半分俺の「善意」なのである(笑)

ま、良い経験になりました(笑)
お客さんのサーバにリモート接続するために、我が家の PC(固定IPで「入口のサーバ」の IPフィルタリングで「接続許可」されている)から putty で「入口のサーバ」をトンネリングして「奥のサーバ」につないでる。 putty で KeepAlive の設定をしているので繋ぎっぱなしで作業している。

しかし、横川の仕事場からは WiFi サービスでインターネットにつないでいるので固定IPではなく「入口のサーバ」の IPフィルタリングを超えられない。

そこで、まず自社のサーバに putty で接続して(固定IPで、「入口のサーバ」の IPフィルタリングで「接続許可」されているサーバ)、そこからお客さんの「入口のサーバ」に ssh 接続。そして「入口のサーバ」から更に ssh で「奥のサーバ」に接続・・・としている。

そしたら、ssh 接続でボロボロタイムアウトするのよ。自宅では常に「奥のサーバ」にも putty で接続していたので、ssh の接続でこれほどタイムアウトするとは知らんかった(^^;

ということで、ssh 接続で KeepAlive するようにしようと思ったんだけどググると「KeepAlive の設定を ~/.ssh/config ファイルに書け」って情報が多い。でも、うちのサーバでもお客さんのサーバでも、全然 config ファイルを読み込まない。もちろん 600 の権限にしてるけどね。

psql で DB に接続して、ちょっとややこしい SQL を考えてると数分でタイムアウト。またうちのサーバから「入口のサーバ」に接続するところからやり直し・・・仕事にならん(^^;;;

そこで、

ssh -o ServerAliveInterval=60 -l hogehoge exsample.com

という具合にコマンドラインで指定したらバッチリ。何時間何もせずにほっておいても ssh のセッションは切れない。
毎回入力するのは面倒くさいので、自社サーバと「入口のサーバ」の .bashrc に

alias ssh='ssh -o ServerAliveInterval=60'

という alias を書いておいた。これで、いつものように ssh -l hogehoge exsample.com で OK。
この年末に、某システムのデータの圧縮方式を LZH から ZIP に変更した。
ユーザーが複数の CSV ファイルをひとつのアーカイブにまとめアップロードしたものを、サーバ(CentOS)上で自動で展開(解凍)し諸々の処理をするシステムだ。

初版公開が 2005年(俺が独立した翌年に作ったシステムだ(笑))なので、当時の Windows のファイル圧縮方式としては LHA(LZH方式)が主流だった。いや、もう、ZIP形式が LZH形式を駆逐してしまう未来は見えていた頃だが、このシステムを使うユーザーの職場ではまだ LZH形式が主流だったのだ。

しかし、あれから 18年。ついにユーザーより「もう、ZIP形式に変更したい~!」という声が出てきた。そのため、解凍コマンドを lha から unzip に変更した際の苦労話は「unzip の日本語ファイル名問題、なんとか解決」というエントリーにもちょっと書いているので、興味がある人は御一読下さいませ(笑)

件のエントリーでは「展開後の日本語ファイル名を EUC-JP で出力する」苦労話をまとめているが、その後、展開したファイルを正しく読み込めないという不具合が発生した。
ログなどを見て、どうもダブルバイト文字を正しく読めていないようだということはわかった。古い Perl のプログラムなので EUC-JP で書かれており、読み込むファイルの中身も EUC-JP である前提で処理をしているようだ。

ユーザーがアップロードするファイルは、Windows で作られているので文字コードは Shift_JIS である。しかし、プログラム内で Shift_JIS を EUC-JP に変換している箇所が無い。なのに、なんで今まではファイルの中身がちゃんと読めてたの???(どこで文字コードが EUC-JP に変換されてるの???) 

まあ、このエントリーのタイトルに思いっきり「落ち」を書いてるけど、lha コマンドでファイルを解凍するときに同時に EUC 変換していたのだ。lha コマンドにはそういうオプションがある。

lhaコマンドの引数には「オプション」と「コマンド」というのがあり、-e と書けば「圧縮ファイルを展開する」というコマンドを設定したことになる。
そのコマンドの前に e と書けば「テキストファイルの文字コードを EUC と相互変換する」というオプションが設定されたことになり、ファイル展開時に自動的にテキストファイルの文字コードが EUC に変換されるのだ。

具体的には、

/usr/local/bin/lha e -e -i -w=./temp hogehoge.lzh

のようなコマンドを投げていた。「e -e」という部分がそうだ。

いやあ、ハマったわ・・・。まさか lha コマンドが EUC 変換までしているとは思いもしなかった・・・(^^;;;
俺が書いたプログラムだけど 18年も前のものなので記憶が・・・

結局、unzip による ZIP ファイルの解凍のあとに、ファイルの中身を EUC 変換する処理を追加して解決した。

昔の UNIX 及び UNIX ライクな OS の主流の文字コードは Shift_JIS ではなく、まだ Unicode も正式に実装されておらず、EUC-JP の一人勝ち状態だった。だから lha にも EUC 変換オプションなんかが実装されているんだろうなあ(笑)
随分前に作った Linux(CentOS)上で動くプログラム。
LZH ファイルを解凍し、そのファイルをほげほげするのだが、さすがにもう Windows 上で LZH ファイルを作るのもきつくなってきた・・・ということで ZIP ファイル対応を依頼されたのだが(例えば、7-Zip なんかでも LZH 形式には対応してないからな(^^;)・・・ハマった(^^;

yum で入れた unzip は -O オプション(アーカイブ内のファイル名のエンコードが指定できる)が使える(以前のバージョンではパッチを当てないと駄目だった)ので、例えば unzip -Ocp932 -l exsample.zip で、exsample.zip の中の「かわいい中年男性一覧.csv」みたいなファイル名は取ってこれるんだけど、これをディスク上に解凍するとファイル名が化けまくる・・・

ちなみに、プログラムは EUC-JP で書かれている。なにせ、もう、18年前に初版公開したプログラムだからな(笑)。

これ、lha コマンドは EUC-JP でファイル名を出力するパッチが当たっていたので問題なかったんだけど、unzip は「サーバの locale のエンコードでファイル名が作られる」ため、実行サーバの locale である UTF-8 のファイル名となる。

他のプログラムにも影響あるから、なんとか EUC-JP でファイル名を設定してほしいなあ。

しかし、unzip にそのようなオプションはない。結局、unzip を実行する前に、locale を EUC-JP にする形でなんとかなった。

(例)
export LC_CTYPE=ja_JP.eucJP; /usr/bin/unzip -OCP932 -d /tmp exsample.zip

このプログラムは実行後シェルを閉じるので、LC_CTYPE の設定を投げっぱなしだが、同一シェル内で他のコマンドなど実行するのなら、

export LC_CTYPE=ja_JP.UTF-8

で locale を元の UTF-8 に戻すこと。

20230529_gmo_con.jpg

昨日、GMOの VPS コンソール経由でサーバ設定を触る必要があったので、vi エディタでコンフィグファイル開いて編集して、「さて保存」と「:w」(コロン、ダブリュー)とコマンドを入れようとしたら・・・

「???入力できない???」

よく見てみると、設定部分でも「:(コロン)」を入れたつもりが「;(セミコロン)」になってる・・・
だからコマンド入力待ちにならないのか・・・

どうも、GMOの VPS コンソール経由でコロンが入力できないのは既知の問題のようだ。ググってみると「Shift + 11」と入力すれば「:.!」という三文字が表示されるので、後ろの二文字を BS で消してコロンだけにしてやればいいらしい。

・・・が、この時はググってる時間も環境もなかったので、一旦 Ctrl + Alt + Del 信号を送ってサーバを再起動し(VPS ポータル画面から再起動すると 15分くらい起動にかかるんだけど、Ctrl + Alt + Del で再起動すると 1~2分で再起動するよ)、バックアップしていたコンフィグファイルをコピーして対応した。

いや、この時点でも十分な設定ではないのだが、これで ssh 接続はできるようになるので、あとは putty から接続して再度設定ファイルを編集した。

まあ、今後はこれでなんとかなるんだけど、こんな変な動き、さっさとどうにかすればいいのに>>>GMO
CentOS 7 上で、Apache を 2.4.6 から 2.4.54 にバージョンアップしたら CGI が実行できなくなった。

一旦 2.4.6 をアンインストールして、iusレポジトリから yum で 2.4.54 をインストールしたんだが、CGI を実行すると Internal Server Error になる。

error_log には、

End of script output before headers: hogehoge.cgi

としか出てない「何が原因がわからないエラー」だ。「End of script output before headers」って、「Content-type: text/html;charset=UTF-8」のようなヘッダ部すら送られない、つまり「プログラムがまったく実行されていない」状態である。

まあ、こういう場合は suEXEC 関係だろうな・・・と思い、/var/log/secure を見てみると、

Jan  7 11:23:42 httpd suexec[15490]: command not in docroot (/home/www/htdocs/hogehoge.cgi)

って。やっぱり「docroot」関連か。

# /usr/sbin/suexec -V
 -D AP_DOC_ROOT="/var/www"
 -D AP_GID_MIN=100
 -D AP_HTTPD_USER="apache"
 -D AP_LOG_SYSLOG
 -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
 -D AP_UID_MIN=500
 -D AP_USERDIR_SUFFIX="public_html"

Document Root が /var/www になっている。
Apache 2.4.6 のときに Document Root を /home で作り直したのだが(DOcument Root が /home/www/htdocs なので)、2.4.54 にした際に suexec コマンドも作り直されてしまった。

suEXEC の設定は、コンフィグファイルのようなもので簡単に指定できない。
再コンパイルしてプログラムを作り直す必要があるのだ。(これがなかなか手間)

ただし、suEXEC 自体はなにかセキュリティ上の問題が出ているわけではないので、2.4.54 で作られる最新のものでなくても問題ないはずだ。
残念ながら、Web サーバ上の suexec は書き換えられてしまったが、予備機にまだ 2.4.6 のときのプログラムが残っている。
FTP で suexec コマンドを持ってきて置いてみた。

・・・が、

# suexec -V
-bash: /usr/sbin/suexec: Permission denied

実行権限エラーが・・・

error_log にも、

Permission denied: exec of '/usr/sbin/suexec' failed

と出ているので、オーナーと実行権限を直してみる。

# chown root:apache /usr/sbin/suexec
# chmod 510 /usr/sbin/suexec
# /usr/sbin/suexec -V
 -D AP_DOC_ROOT="/home"
 -D AP_GID_MIN=100
 -D AP_HTTPD_USER="apache"
 -D AP_LOG_SYSLOG
 -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
 -D AP_UID_MIN=500
 -D AP_USERDIR_SUFFIX="public_html"

実行できた。
ちゃんと suEXEC で実行される CGI のある Document Root が /home 以下になっている。ばっちり。

しかし、これで、error_log に Permission denied は出なくなったがやっぱり CGI は実行されない。

/var/log/secure には「failed to setgid」と。

Jan 09 22:00:50 httpd suexec[31741]: uid: (1001/hogeusr) gid: (1001/hogegrp) cmd: hogehoge.cgi
Jan 09 22:00:50 httpd suexec[31741]: failed to setgid (1001: hogehoge.cgi)

そうかそうか。結局、SUID 設定をしないとダメなのだな。

# chmod u+s /usr/sbin/suexec
# ls -la /usr/sbin/suexec
-r-s--x--- 1 root apache 15368 Apr  3  2020 /usr/sbin/suexec

これで、ばっちり CGI も suEXEC 有効で実行されるようになった。

今後は、Apacbe のバージョンアップをするときに suexec コマンドを別名で退避しておいて、Apache インストール後にもとに戻すようにしよう。
Raspberry Pi を監視カメラ装置として使おうと思うので、起動時は X Window System の GUI 環境ではなく、コンソールの CLI 環境で起動したい。

なんか、これもググってみると、raspi-config を起動してメニューから設定・・・という内容が多い。
これも、誰かが最初に作った説明ページを見て、真似て同じようなページを作る輩の仕業だな(笑)

GUI から CLI に切り替えるのに、いちいちメニュー画面なんか起動しなくていいよ。

raspi-config コマンドは nonint オプションをつけると Non-Interactive(ノンインタラクティブ)モードで実行されるので、こっちの方が簡単。

まず、現在の起動モードを確認。

root@camera1:~# raspi-config nonint get_boot_cli
1

結果が 1 のときは GUI、0 のときは CLI で起動する。
現在は 1 なので、X Window System が起動する。

CLI 起動に変更する。

root@camera1:~# raspi-config nonint do_boot_behaviour B1

で、起動モードを確認。

root@camera1:~# raspi-config nonint get_boot_cli
0

結果が 0 なので、今後は起動時に CLI モードで起動する。

あとは reboot してみて確認しよう。

いつも散々「UNIX系OS(Linux も含む)で設定変えるたびに reboot するやつ、めっちゃ格好悪い」て言うてますが、今回は「起動時の画面設定」だからね。再起動してみないと結果はわからない。

ちなみに、CLI から GUI に変えるときは、

root@camera1:~# raspi-config nonint do_boot_behaviour B3

である。
いや、ずっとサーバ管理をやってる人には常識だったんだろうけど・・・

最近の bind って(ver 9.8以降)、マスターサーバからコピーしてきたスレーブサーバの zone ファイルって raw 形式っていう、いわゆるバイナリデータになってるんだね。

いつもの調子で、

# cat chroot/var/named/slaves/exsample.com.zone

なんてやったら、画面がぐちゃぐちゃに乱れてビビったわ(笑)

named-compilezone というコマンドで、text 形式に変換して表示できるということなのでやってみた。

# named-compilezone -f raw -F text -o - exsample.com chroot/var/named/slaves/exsample.com.zone
zone exsample.com/IN: loaded serial 2021091501
exsample.com.               28800 IN SOA  serv1.exsample.com. root.serv1.exsample.com. 2021091502 21600 3600 604800 28800
<略>
OK

おお、ちゃんと表示された。

ちなみに、コマンド引数の意味は、

named‐compilezone -F text -f raw -o (出力ファイル名) (ゾーン名) (ゾーンファイル名)

である。

出力ファイル名を '-' とだけしておけば、標準出力に出力される。
ゾーン名は、そのゾーンファイルに設定されているドメイン名ね。
ゾーンファイル名については、「ファイル名だけでパスは必要ない」と説明しているサイトがあるが嘘です。ちゃんとパスまで指定しないとファイルが見つからなくて、

dns_master_load: file format mismatch
zone exsample.com/IN: loading from master file exsample.com.zone failed: not implemented
zone exsample.com/IN: not loaded due to errors.

みたいなエラーになるぞ。「file format mismatch」って出てるけど、ちゃんとスレーブの zone ファイルが見つけられてないだけだ。「chroot/var/named/slaves/exsample.com.zone」みたいにフルパスで指定すれば問題なく実行される。

あと、named.conf の options に「masterfile‐format text;」を追加すれば、バイナリではなくテキストで出力されるらしんだけど、うちの環境ではエラーが出て bind が起動しなかった。

まあ、別にバイナリでも named-compilezone コマンドで確認できるからいいけど。

AlmaLinux 8.4 は、CentOS 8 の互換 OS だ。
そのため、CentOS 8 と同じで、TCP Wrapper が廃止され、今までのように /etc/hosts.allow や /etc/hosts.deny で IP アドレスによるアクセス制限がかけられなくなった。ファイアウォール(firewalld)で制限をかけることになる。

CentOS 8 を触ったことがなかったもんで(最近設定したのも、サポートのことを考えて CentOS 7 だったからなあ)、/etc/hosts.allow を編集しようと思ったらなかったので驚いた。

まず、自宅 PC や既存サーバなど、恒常的に存在している機器はパーマネントルール(設定ファイルに書き込まれ、再起動時にも有効となるルール)を投入。

# firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="202.XXX.XXX.12" port protocol="tcp" port="22" accept"
# firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="176.XXX.XXX.65" port protocol="tcp" port="22" accept"

で、元々の設定は「誰でも大歓迎」になっているので、その設定を削除。

# firewall-cmd --remove-service=ssh --zone=public --permanent

これで、設定ファイル(/etc/firewalld/zones/public.xml)に書き込まれる。
まだ、この時点では設定ファイルが編集されただけなので、設定ファイルを読み込み直して設定を反映させる。

# firewall-cmd --reload

これで、202.XXX.XXX.12、176.XXX.XXX.65 の IP アドレスからのみ ssh 接続が可能となる。

次に、一時的に接続を許すランタイムルールで職場の PC からの接続を許す。(引数 permanent を付けてないだけ)

# firewall-cmd --zone=public --add-rich-rule="rule family="ipv4" source address="114.XXX.XXX.72" port protocol="tcp" port="22" accept"

設定ファイルには書き込まれないので、reload は不要。即設定が反映する。

必要なくなったら、

# firewall-cmd --zone=public --remove-rich-rule="rule family="ipv4" source address="114.XXX.XXX.72" port protocol="tcp" port="22" accept"

で削除。

旧サーバ(CentOS)では Web 経由で /etc/hosts.allow を編集する仕組みを作って、外出先から一時的に ssh 接続を許すようにしてたんだけど使えなくなっちゃったな。
新しい仕組み作らないと・・・

現在借りているホスティングサーバがとうとう契約切れとなるので(なにせ、OS が CentOS 4.8だからな(笑))、新たに某クラウドサービスを利用して代替サーバを用意したんだけど、OS は AlmaLinux 8.4 にしてみた。

CentOS 7.7、CentOS 8.1 が選べるけど、もう先の無い OS を今更選択するのも賢いやり方ではあるまい。まあ、7.7 を選んでおけば、2024年の 6月いっぱいサポートは受けられるけど(笑)。だからといって今更 7.7 ってのもなあ。

AWS は CentOS Stream が用意されてるんだっけ?
今回契約したクラウドサービスには CentOS、Ubuntu、Debian、そして CentOS 互換の AlmaLinux、Rocky Linux が用意されている。
この選択肢なら、AlmaLinux か Rocky Linux で、一歩先行している(安定版の提供が 1ヶ月ほど早かった)AlmaLinux に決定と・・・。

でも、実際にサーバが使えるようになるのは明日以降。
まだ AlmaLinux を触ったことは無い。なので、実際の CentOS との互換というのはどの程度なのか。

yum は使えるんよなあ???

もし七転八倒することになったら、その様子はこのブログにて(笑)

このアーカイブについて

このページには、過去に書かれたブログ記事のうちUNIXやLinuxカテゴリに属しているものが含まれています。

前のカテゴリはMacです。

次のカテゴリはWindowsです。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

月別 アーカイブ

電気ウナギ的○○ mobile ver.

携帯版「電気ウナギ的○○」はこちら