目次: Linux
前回(2026年1月29日の日記参照)、スクリプトの先頭(例えばシェルスクリプトなど)に書く"#!〜"から始まるおまじないのことをshebangといって、カーネルがexecveシステムコール内で解釈する文字列であることを紹介しました。
また、前々回(2026年1月23日の日記参照)は、shebangは間違っていても動いてしまう場合があることも紹介しました。もう少し正確に言うとexecveシステムコールに渡すとエラーになるスクリプトもシェルで実行できる場合があります。例えばこんな感じです。
#!/bin/dash
echo ok
##!/bin/dash
echo ng
$ ./ok.sh ok $ ./ng.sh ng
なぜかexecveシステムコールがエラーになるスクリプトでも実行できます。不思議ですよね。
大抵のシェルには、初めにexecveで実行して、失敗したらシェルスクリプトだと思ってシェルに渡して実行する仕組みがあります。実際にコードを見てみましょう。シェルは何でも良いと思われますが、Debianならdashでしょってことでdashを見ます。
// dash/src/exec.c
STATIC void
tryexec(char *cmd, char **argv, char **envp)
{
char *const path_bshell = _PATH_BSHELL;
repeat:
#ifdef SYSV
do {
execve(cmd, argv, envp);
} while (errno == EINTR);
#else
execve(cmd, argv, envp);
#endif
if (cmd != path_bshell && errno == ENOEXEC) {
*argv-- = cmd;
*argv = cmd = path_bshell;
goto repeat;
}
}
上記のtryexec()関数が先程言った通りの実装になっています。まずexecve()を実行します、成功したら返ってこないのでそれでおしまいです。失敗したらexecve()から返ってくるので、argvを一個ずらしてコマンド名をスクリプトからシェルに変更して再びexecve()を実行します。これは文字で説明してもわかりにくいので、下記にcmdとargvの変化を示します。
先頭のほうで出てくる_PATH_BSHELLはシェルのフルパス文字列を定義したマクロです。
# dash/configure.ac
dnl Check for declarations
AC_CHECK_DECL([_PATH_BSHELL],,AC_DEFINE_UNQUOTED([_PATH_BSHELL], "/bin/sh", [Define to system shell path]),[
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
])
マクロ_PATH_BSHELLはconfigureのときに決定されます。通常は/usr/include/paths.hが定義しているはずで、私の環境では/bin/shになっていました。もし定義されていない環境の場合はdash側で決めますが、これも/bin/shになるようです。
スクリプトの中身に関わらずシェルスクリプトだと仮定して実行するだけですから、スクリプトがシェルスクリプトでなければエラーになります。やや特殊ケースとして、シェルスクリプトであってもシェル依存の専用構文(bashやzshの専用構文)を使うと実行エラーになります。
わざとbash専用の構文を使ったスクリプトを2つ作ります。片方はshebangが正しく、もう片方はshebangを誤った文字列にしてあり、それ以外は全く同じです。
#### ok_bash.sh
#!/bin/bash
function a()
{
echo hello
}
a
#### ng_bash.sh
##!/bin/bash
function a()
{
echo hello
}
a
この2つのスクリプトをdash上で実行しようとすると、下記のようになります。ok_bash.shは実行できますが、ng_bash.shは実行できません。
$ ./ok_bash.sh
hello
$ ./ng_bash.sh
./ng_bash.sh: 3: Syntax error: "(" unexpected
最初のok_bash.shはshebangに書かれた通りbashが起動されるので、bash専用の構文も実行できます。
2つ目のng_bash.shはshebangが間違っていてexecveで実行できないため、dashはスクリプトを/bin/sh = dash上で実行しようと試みます。しかしdashでは使えない構文が含まれているためエラーとなります。
この記事にコメントする
目次: 自宅サーバー
一昨年(2024年2月2日の日記参照)にJPRSドメイン認証型SSLを設定しました。年間990円とお安く使えて良かったのですが、サービス終了してしまうらしく、今月から先の継続ができなくなりました。
後継サービスはJPRSドメイン認証型SSL(自動更新)だと思われますが、特に何も変わってなさそうなのに、なぜか料金が年間2,200円(2.5倍)になっていました。値上げするなとは言わないけど、無言で2.5倍にするのはどうなんだ。嘘でもいいから「こんなに良くなりました」くらい言ってほしい……。
そんなこんなでJPRSのSSLとおさらばしてLet's Encryptに変更しました。無料なうえにボタン1個押すだけなのでめちゃ楽です。とてもありがたいんですけど、Let's Encrypt以外を選択する人って居るんだろうか……?
この記事にコメントする
目次: 車
以前(2025年11月21日の日記参照)、ジャガーさんの左前をぶつけてバンパーをガリガリにしてしまいました。1か月前にいい加減直そうと思い立ち修理の予約をしたところ、予約が混んでいたらしくめちゃくちゃ先の日付になってしまいました。
で、今日はいよいよ修理工場に車を持っていく日でした、が……朝起きたら外は雪で真っ白でした……。ええ、なんで今日に限って雪が降る?
一瞬、頑張れば行けるか……?とも考えましたが、夏タイヤで下手に走って一か所でも凍っていたり積雪があったら終わりですし、事故ったら修理もへったくれもないです。修理工場にお電話して予約キャンセルしました。また予約するしかないな〜。
この記事にコメントする
| < | 2026 | > | ||||
| << | < | 02 | > | >> | ||
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
26年1月23日
26年1月23日
24年12月9日
24年12月9日
25年12月18日
25年12月18日
25年12月18日
25年11月28日
25年11月28日
25年11月28日
25年10月6日
25年10月6日
25年9月29日
25年9月29日
20年8月24日
20年8月24日
16年2月14日
16年2月14日
25年7月20日
25年7月20日
wiki
Linux JM
Java API
2002年
2003年
2004年
2005年
2006年
2007年
2008年
2009年
2010年
2011年
2012年
2013年
2014年
2015年
2016年
2017年
2018年
2019年
2020年
2021年
2022年
2023年
2024年
2025年
2026年
過去日記について
アクセス統計
サーバ一覧
サイトの情報合計:
本日: