コマンドの前にbash stat()とaccess()が多すぎます。普通ですか?

コマンドの前にbash stat()とaccess()が多すぎます。普通ですか?

実行するように指示されたシェルで実行すると、strace実際のバイナリが実行される前に広範な統計を示す次の出力が得られます。bashmkdirmkdir

BASH$> strace -f sh -c "bash -c \"mkdir /tmp\" 2>&1 | nl | grep -e "execve\|stat\|access" 
[.....]
  2766  [pid 17371] stat(".", {st_mode=S_IFDIR|0750, st_size=17262, ...}) = 0
  2767  [pid 17371] stat("/usr/local/sbin/mkdir", 0x7ffd87aad0a0) = -1 ENOENT      2767 (No such file or directory)
  2768  [pid 17371] stat("/usr/local/bin/mkdir", 0x7ffd87aad0a0) = -1 ENOENT (No such file or directory)
  2769  [pid 17371] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
  2770  [pid 17371] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
  2771  [pid 17371] access("/usr/bin/mkdir", X_OK) = 0
  2772  [pid 17371] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
  2773  [pid 17371] access("/usr/bin/mkdir", R_OK) = 0
  2774  [pid 17371] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
  2775  [pid 17371] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
  2776  [pid 17371] access("/usr/bin/mkdir", X_OK) = 0
  2777  [pid 17371] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
  2778  [pid 17371] access("/usr/bin/mkdir", R_OK) = 0
  2779  [pid 17371] execve("/usr/bin/mkdir", ["mkdir", "/tmp"], 0x557ec7e15920 /* 5 vars */) = 0

/usr/bin/mkdir stat()私の質問は:頻繁に編集されるのが普通ですか(それではなぜですか?)出力ラインには番号が付けられています。特にこの行が実行され2776たらどういう意味があるのか​​知りたいです2771。また、私はbashがすぐに情報を提供する必要があるため、2770すべてのシステムコールを最初から最後まで保存するという印象を受けました。私は何を見逃していますか?execvestat

以降の説明を調べて、代替dashシェルがどのように機能するかを確認し、次のstat()内容も表示されます。

DASH$> strace -f sh -c "dash -c \"mkdir /tmp\" 2>&1 | nl | grep -e "execve\|stat\|access" 
[....]
  2792  [pid 17372] stat("/usr/local/sbin/mkdir", 0x7ffc66010b50) = -1 ENOENT (No such file or directory)
  2793  [pid 17372] stat("/usr/local/bin/mkdir", 0x7ffc66010b50) = -1 ENOENT (No such file or directory)
  2794  [pid 17372] stat("/usr/sbin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
  2795  [pid 17372] execve("/usr/sbin/mkdir", ["mkdir", "/run"], 0x55d8d3453bb8 /* 6 vars */) = 0

私は27922793が2768 PATH`行に似ていることを知っています。2767are because of searching the executable in the various directories in the current

これがセール中であれば、一統計dashだけしてbash10回だけしてください。もう一度質問:これは普通ですか?

修正する:Bash統計には、より多くのgeteuid()getguid()およびgetuid()混合項目があります。getgid()

BASH$>strace -f sh -c "bash -c \"mkdir /tmp\"" 2>&1 | grep -e "execve\|stat\|access\|geteuid\|getegid\|getuid\|getgid" 
[....]
[pid 24534] stat("/usr/local/bin/mkdir", 0x7fffda480f30) = -1 ENOENT (No such file or directory)
[pid 24534] stat("/usr/local/sbin/mkdir", 0x7fffda480f30) = -1 ENOENT (No such file or directory)
[pid 24534] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
[pid 24534] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
[pid 24534] geteuid()                   = 1000
[pid 24534] getegid()                   = 1000
[pid 24534] getuid()                    = 1000
[pid 24534] getgid()                    = 1000
[pid 24534] access("/usr/bin/mkdir", X_OK) = 0
[pid 24534] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
[pid 24534] geteuid()                   = 1000
[pid 24534] getegid()                   = 1000
[pid 24534] getuid()                    = 1000
[pid 24534] getgid()                    = 1000
[pid 24534] access("/usr/bin/mkdir", R_OK) = 0
[pid 24534] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
[pid 24534] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
[pid 24534] geteuid()                   = 1000
[pid 24534] getegid()                   = 1000
[pid 24534] getuid()                    = 1000
[pid 24534] getgid()                    = 1000
[pid 24534] access("/usr/bin/mkdir", X_OK) = 0
[pid 24534] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
[pid 24534] geteuid()                   = 1000
[pid 24534] getegid()                   = 1000
[pid 24534] getuid()                    = 1000
[pid 24534] getgid()                    = 1000
[pid 24534] access("/usr/bin/mkdir", R_OK) = 0
[pid 24534] execve("/usr/bin/mkdir", ["mkdir", "/tmp"], 0x55adcd4dc040 /* 55 vars */) = 0

それでは、これが「ここで何が起こっているのか」についての手がかりを提供できますか?悪用を防ぐためにいくつかのテストが実施されていますかsetuid

**更新2:** geteuid()getguid()およびgetuid()アクセスの組み合わせは、ライブラリ機能の使用の特徴であるようですgetgid()。使用するたびにbashが実行されるため、all、およびを使用します。glibcint eaccess(const char *pathname, int mode);eaccessgeteuidgetguidgetuidgetgidaccessfindcmd.c関数はfile_statusこのようにeaccessを2回実行します。

#if defined (HAVE_EACCESS)
  /* Use eaccess(2) if we have it to take things like ACLs and other
     file access mechanisms into account.  eaccess uses the effective
     user and group IDs, not the real ones.  We could use sh_eaccess,
     but we don't want any special treatment for /dev/fd. */
  if (eaccess (name, X_OK) == 0)
    r |= FS_EXECABLE;
  if (eaccess (name, R_OK) == 0)
    r |= FS_READABLE;

これらの各eaccessは、4つのシステムコールに接続できます。

ベストアンサー1

ループを見てください。findcmd.c:find_user_command_in_path()

stat()(からfile_status())パスの各要素を2回:find_in_path_element()at行を介して1回640is_directory()atラインを通って一度645話

おっしゃった通りfile_status()いわゆるeaccess()

これは最適化できますが、パスがハッシュされ、これらのすべての検索と統計はコマンドが最初に使用されたときにのみ発生するため、大きな問題ではないことに注意してください。

おすすめ記事