我可以为子命令起别名吗? (缩短 `docker ps` 的输出)

Can I alias a subcommand? (shortening the output of `docker ps`)

docker 命令有一个 ps 发出很长行的子命令:

$ docker ps -a
CONTAINER ID        IMAGE                             COMMAND                  CREATED             STATUS                      PORTS                                                                                                                                                                                                                                                                                                        NAMES
6e8ec8a16da4        waisbrot/wait:latest              "/wait"                  4 minutes ago       Exited (0) 4 minutes ago                                                                                                                                                                                                                                                                                                                 wait-for-janus-test
9dbf0739561f        whoop/downsampler:master          "./run.bash"             4 minutes ago       Up 4 minutes                0.0.0.0:32855->4369/tcp, 0.0.0.0:32854->9100/tcp, 0.0.0.0:32853->9101/tcp, 0.0.0.0:32852->9102/tcp, 0.0.0.0:32851->9103/tcp, 0.0.0.0:32850->9104/tcp, 0.0.0.0:32849->9105/tcp, 0.0.0.0:32848->9106/tcp, 0.0.0.0:32847->9107/tcp, 0.0.0.0:32846->9108/tcp, 0.0.0.0:32845->9109/tcp, 0.0.0.0:32844->9110/tcp   metrics-downsampler-test
6cf56623bb48        whoop/janus:master                "./start.bash"           4 minutes ago       Up 4 minutes                0.0.0.0:32843->80/tcp                                                                                                                                                                                                                                                                                        janus-test
882b50303d54        whoop/recalculator:master         "./run.bash"             4 minutes ago       Exited (1) 4 minutes ago                                                                                                                                                                                                                                                                                                                 internum-test

可以指示只输出特定的列:

docker ps --format "table {{.Image}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}"

我希望能够说 docker ps 并为我添加 --format "table..." 参数。有没有好的方法来做到这一点?

我知道我可以说

alias dp='docker ps --format ...'

但我更愿意保留子命令。

我正在使用 zsh 作为我的 shell。

您可以将 docker 包装在一个函数中,该函数检查特定的子命令并传递其他所有内容。 (下面的内容实际上不仅适用于 zsh,而且适用于任何 POSIX-compliant shell -- zsh 不属于的类别)。

docker() {
  case  in
    ps)
      shift
      command docker ps --format 'table {{.Image}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}' "$@"
      ;;
    *)
      command docker "$@";;
  esac
}

如果你想要一个更通用的包装函数(不需要知道你想要的特定 ps 逻辑),可以按如下方式完成(注意这个版本是 与基线 POSIX sh 兼容,因为它使用了 local;然而,这是一个扩展,甚至由 ash 及其衍生产品实现):

docker() {
  local cmd=; shift
  if command -v "docker_$cmd" >/dev/null 2>/dev/null; then
    "docker_$cmd" "$@"
  else
    command docker "$cmd" "$@"
  fi
}

...之后,任何子命令都可以定义自己的函数,而无需修改包装器来了解它们(您也可以在名为 docker_ps 的 PATH 中创建一个脚本,或提供以您选择的任何其他方式执行命令):

docker_ps() {
  command docker ps --format 'table {{.Image}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}' "$@"
}

您可以为子命令设置别名。 使用别名,您仍然可以像键入完整命令一样获得漂亮的 zsh 补全。这就是为什么我更喜欢它们而不是函数。

您的别名相当于:

alias dp='docker ps --format "table {{.Image}}\t{{.Names}}\t{{.Ports}}'\t{{.Status}}"

但现在似乎建议使用完整的命令,并且 ls 已替换 ps,这使您现在的别名:

alias dp='docker container ls --format "table {{.Image}}\t{{.Names}}\t{{.Ports}}'\t{{.Status}}"

一切都有 docker 别名真是太好了。为此,我一直在研究一组 comprehensive aliases,它会让您的别名类似于:

alias ddcls='docker container ls --format "table {{.Image}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}"

使用Docker配置

因为这基本上是 docker 问题,而不是 bash 问题,所以您甚至不需要别名。 Docker CLI 允许您在自己的配置文件中自定义这些命令!来自 Container 42 的这个重要提示:

  1. 创建或找到您的 docker 配置文件(如果您曾经使用过 docker login 它应该已经创建了。

    ~/.docker/config.json
    
  2. 然后添加 docker 的默认格式,以便每次 运行 将 ps 命令用作顶级 属性配置:

    {
        "psFormat": "table {{.Image}}\t{{.Names}}\t{{.Ports}}\t{{.Status}}",
    }
    
  3. 然后 运行 docker ps 像平常一样:

PS格式

Docker 使用 go templates and has a list of the valid placeholders:

Command Description
.ID Container ID
.Image Image ID
.Command Quoted command
.CreatedAt Time when the container was created.
.RunningFor Elapsed time since the container was started.
.Ports Exposed ports.
.Status Container status.
.Size Container disk size.
.Names Container names.
.Labels All labels assigned to the container.
.Label Value of a specific label for this container.
.Mounts Names of the volumes mounted in this container.
.Networks Names of the networks attached to this container.

替代解决方案/线程

在我的例子中,我只需要禁用 docker login 命令(有些人在我们的 CI-runner 上使用该命令破坏了 docker 的通用配置文件)。 所以,我添加到我的 .bashrc:

_docker() {
  if [ "" = "login" ]; then
    echo "login is disabled, to login please update a config file manually!"
    return
  fi
  
  /usr/bin/docker "$@"
}

alias docker="_docker"