AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 705522
Accepted
dotancohen
dotancohen
Asked: 2022-06-10 00:26:38 +0800 CST2022-06-10 00:26:38 +0800 CST 2022-06-10 00:26:38 +0800 CST

如何知道什么是命令、系统调用、bash 内置函数等?

  • 772

一位同事最近问“什么是man”?在得知并非所有可从 Bash CLI 访问的东西都是命令后,我很谨慎地调用man命令。

man man只是称它为接口:

NAME
       man - an interface to the on-line reference manuals

man有一个可执行文件:

$ which man
/usr/bin/man
$ file /usr/bin/man
/usr/bin/man: ELF 64-bit LSB shared object

程序也是如此man,因为它有一个可执行文件?其他名词可以man是什么?用什么名词来形容呢?真的,我对如何确定任意是什么的一般情况感兴趣,这只是一个thing on the cli例子man。

就此而言,可以在 Bash CLI 上使用的所有东西是什么词?一个包含命令、别名、系统调用等的词?

command-line terminology
  • 3 3 个回答
  • 891 Views

3 个回答

  • Voted
  1. Stephen Kitt
    2022-06-10T00:53:40+08:002022-06-10T00:53:40+08:00

    在 POSIX 术语中,任何可以要求 shell 做某事的东西都是命令:

    用于执行特定任务的 shell 指令。

    所以

    man man
    

    是一个命令,原样(技术上)

    man
    

    man也是一个实用程序:

    一个程序,不包括作为 Shell 命令语言的一部分提供的特殊内置实用程序,可以从 Shell 按名称调用以执行特定任务或相关任务集。

    (这里的排除并不重要;之所以提到它,是因为特殊的内置实用程序具有特定的属性。)

    要找出给定命令是什么,请使用type. 这将告诉您它是内置的,还是PATH(以及在哪里)上的程序,或别名等(或未知)。

    请注意,系统调用不能用作 shell 命令。

    另请参阅它们是命令还是实用程序?内置命令和非内置命令有什么区别?

    • 9
  2. MC68020
    2022-06-10T03:23:49+08:002022-06-10T03:23:49+08:00

    从最低层开始:

    系统调用

    系统调用是用户态任务(必须)用来从内核请求某些服务并运行到特权内核模式的方式。

    例如,假设 C 是您的编程语言,并且您希望您的任务更改其当前目录,您需要在程序中插入chdir()指令。

    当然,这些过程不能立即从命令行访问。vg 在命令行输入 chdir 不会调用 chdir 系统调用。

    所有可用系统调用的列表当然取决于内核,唯一可靠的来源当然是include/linux/syscalls.h内核源代码分发的头文件。

    指示

    CLI 是您正在运行的任务的接口。您输入的任何内容都称为指令,因为它应该指示任务完成某些操作。

    命令

    您键入的内容将首先通过解释器,该解释器将对您键入的标记执行一些词法分析,并且在 shell 的特定情况下,可能会识别命令的名称(理解为不是变量赋值)并顺便决定它需要求助于另一个程序才能满足您的要求。然后它将派生一个子进程,该子进程将执行该其他程序的二进制文件。

    但是在某些特殊情况下,任务可能更容易满足请求,而无需借助外部程序(例如微积分),或者更重要的是,必须在内部执行您的请求。

    内置命令

    回到我们最初更改活动目录的意愿,用户将发出众所周知的 shell 命令cd。用户真正想要的是改变他的 shell 的当前目录。而且因为 chdir 系统调用只改变调用者的当前工作目录,shell 不能派生另一个不会改变其父进程的进程。shell 必须在内部执行 chdir 系统调用。

    yourshellname所有手册页中都列出了 shell 内置命令。

    别名

    别名只不过是任何用户都可以设置的同义词,并将由命令行解释器翻译成所需的字符串(应该代表对 shell 的任何合法指令。)

    alias借助 shell 内置命令,可以获得所有当前活动别名的列表。

    • 5
  3. Best Answer
    sudodus
    2022-06-10T04:06:41+08:002022-06-10T04:06:41+08:00

    我有一个小的 shellscript,可以帮助我识别命令:它是什么类型的命令,如果通过程序包安装,是哪个包。也许用名字what-about,

    #!/bin/bash
    
    LANG=C
    inversvid="\0033[7m"
    resetvid="\0033[0m"
    
    if [ $# -ne 1 ]
    then
     echo "Usage: ${0##*/} <program-name>"
     echo "Will try to find corresponding package"
     echo "and tell what kind of program it is"
     exit 1
    fi
    command="$1"
    
    str=;for ((i=1;i<=$(tput cols);i++)) do str="-$str";done
    tmp="$command"
    first=true
    curdir="$(pwd)"
    tmq=$(which "$command")
    tdr="${tmq%/*}"
    tex="${tmq##*/}"
    if test -d "$tdr"; then cd "$tdr"; fi
    #echo "cwd='$(pwd)' ################# d"
    
    while $first || [ "${tmp:0:1}" == "l" ]
    do
     first=false
     tmp=${tmp##*\ }
     tmq="$tmp"
     tmp=$(ls -l "$(which "$tmp")" 2>/dev/null)
     tdr="${tmq%/*}"
     tex="${tmq##*/}"
     if test -d "$tdr"; then cd "$tdr"; fi
    # echo "cwd='$(pwd)' ################# d"
     if [ "$tmp" == "" ]
     then
      tmp=$(ls -l "$tex" 2>/dev/null)
      tmp=${tmp##*\ }
      if [ "$tmp" == "" ]
      then
       echo "$command is not in PATH"
    #   package=$(bash -ic "$command -v 2>&1")
    #   echo "package=$package XXXXX 0"
       bash -ic "alias '$command' > /dev/null 2>&1" > /dev/null 2>&1
       if [ $? -ne 0 ]
       then
        echo 'looking for package ...'
        package=$(bash -ic "$command -v 2>&1"| sed -e '0,/with:/d'| grep -v '^$')
       else
        echo 'alias, hence not looking for package'
       fi
    #   echo "package=$package XXXXX 1"
       if [ "$package" != "" ]
       then
        echo "$str"
        echo "package: [to get command '$1']"
        echo -e "${inversvid}${package}${resetvid}"
       fi
       else
        echo "$tmp"
       fi
     else
      echo "$tmp"
     fi
    done
    tmp=${tmp##*\ }
    if [ "$tmp" != "" ]
    then
     echo "$str"
     program="$tex"
     program="$(pwd)/$tex"
     file "$program"
     if [ "$program" == "/usr/bin/snap" ]
     then
      echo "$str"
      echo "/usr/bin/snap run $command     # run $command "
      sprog=$(find /snap/"$command" -type f -iname "$command" \
       -exec file {} \; 2>/dev/null | sort | tail -n1)
      echo -e "${inversvid}file: $sprog$resetvid"
      echo "/usr/bin/snap list $command    # list $command"
      slist="$(/usr/bin/snap list "$command")"
      echo -e "${inversvid}$slist$resetvid"
     else
      package=$(dpkg -S "$program")
      if [ "$package" == "" ]
      then
       package=$(dpkg -S "$tex" | grep -e " /bin/$tex$" -e " /sbin/$tex$")
       if [ "$package" != "" ]
       then
        ls -l /bin /sbin
       fi
      fi
      if [ "$package" != "" ]
      then
       echo "$str"
       echo " package: /path/program  [for command '$1']"
       echo -e "${inversvid} $package ${resetvid}"
      fi
     fi
    fi
    echo "$str"
    #alias=$(grep "alias $command=" "$HOME/.bashrc")
    alias=$(bash -ic "alias '$command' 2>/dev/null"| grep "$command")
    if [ "$alias" != "" ]
    then
     echo "$alias"
    fi
    type=$(type "$command" 2>/dev/null)
    if [ "$type" != "" ]
    then
     echo "type: $type"
    elif [ "$alias" == "" ]
    then
     echo "type: $command: not found"
    fi
    cd "$curdir"
    

    有时有两种选择,例如 for echo,一个单独的编译程序和 shell 内置命令。除非您使用单独程序的完整路径,否则内置的 shell 将获得优先权并被使用,

    $ what-about echo
    -rwxr-xr-x 1 root root 35000 jan 18  2018 /bin/echo
    ----------------------------------------------------------------------------------
    /bin/echo: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically
    linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0,
    BuildID[sha1]=057373f1356c861e0ec5b52c72804c86c6842cd5, stripped
    ----------------------------------------------------------------------------------
     package: /path/program  [for command 'echo']
     coreutils: /bin/echo 
    ----------------------------------------------------------------------------------
    type: echo is a shell builtin
    

    有时命令链接到可能隐藏的程序,例如rename我使用的版本,

    $ what-about rename
    lrwxrwxrwx 1 root root 24 maj 12  2018 /usr/bin/rename -> /etc/alternatives/rename
    lrwxrwxrwx 1 root root 20 maj 12  2018 /etc/alternatives/rename -> /usr/bin/file-rename
    -rwxr-xr-x 1 root root 3085 feb 20  2018 /usr/bin/file-rename
    ----------------------------------------------------------------------------------
    /usr/bin/file-rename: Perl script text executable
    ----------------------------------------------------------------------------------
     package: /path/program  [for command 'rename']
     rename: /usr/bin/file-rename 
    ----------------------------------------------------------------------------------
    type: rename is /usr/bin/rename
    

    为了避免错误,我有一个别名rm,并且别名优先于PATH. 您可以使用反斜杠作为前缀,\rm以跳过别名并直接运行程序。(请记住,别名仅适用于特定用户,而不适用于sudo其他用户,除非他们定义了类似的别名。)

    $ what-about rm
    -rwxr-xr-x 1 root root 63704 jan 18  2018 /bin/rm
    ---------------------------------------------------------------------------
    /bin/rm: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV),
    dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for
    GNU/Linux 3.2.0, uildID[sha1]=864c9bbef111ce358b3452cf7ea457d292ba93f0,
    stripped
    ---------------------------------------------------------------------------
     package: /path/program  [for command 'rm']
     coreutils: /bin/rm 
    ---------------------------------------------------------------------------
    alias rm='rm -i'
    type: rm is /bin/rm
    
    • 2

相关问题

  • ip 命令是否支持通配符?

  • 需要许多参数的实用程序的推荐界面是什么?[关闭]

  • 远程运行 X 应用程序,在远程主机上运行 GUI [关闭]

  • 使 mysql CLI 以交互方式向我询问密码

  • 没有服务器的命令行 pub/sub?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve