【问题标题】:bash + cmd : Pass one command output into second commandbash + cmd :将一个命令输出传递给第二个命令
【发布时间】:2019-08-04 02:54:33
【问题描述】:

我试图将一个命令的输出传递给另一个命令,但没有成功。 我尝试将目录中的所有.yaml 文件列出到一个逗号分隔的字符串中,并将结果传递给另一个命令。

这是我目前得到的:

我正在使用这个命令:

ls *.yaml -p | grep -v / | tr '\n' ','

列出所有创建为逗号分隔的文件,输出如下:

api-pod.yaml,login-pod.yaml,mongo-pod.yaml,web-pod.yaml,

(注意后面有命令)

现在,我需要将此输出传递给kubectl apply -f 命令

kubectl apply -f (the output)

到目前为止我已经尝试过:

  • kubectl apply -f $(ls *.yaml -p | grep -v / | tr '\n' ',')
  • kubectl 应用 -f ls *.yaml -p | grep -v / | tr '\n' ','
  • for /F "usebackq delims=" %A in (ls *.yaml -p | grep -v / | tr '\n' ',') 做 kubectl apply -f %A

但没有一个对我有用。我已经尝试过cmd 和 bash(Windows 上的MINGW64

可以在 Linux (bash) 和 Windows (cmd) 中运行的解决方案会很棒,但如果不存在,我将使用基于 Linux 的解决方案。

谢谢!

编辑:(也许)重要的是要注意我从 Makefile 运行命令

kompose:
    # this will generate all the .yaml files
    kompose convert
    # this doesn't work for me
    kubectl apply -f "$(ls *.yaml -p | tr '\n' ',')"
    # this doesn't work for me either
    kubectl apply -f "$(find . -maxdepth 1 -name "*.yaml" -type f -printf "%f,")"

并使用make kompose 运行它

另一个编辑:

运行 @RicoChen 解决方案直接在 MINGW 中为我工作,但不适用于 Makefile(如果有人知道为什么会受到赞赏)

我相信你们提到的所有解决方案都可以在真正的 linux bash 中完美运行。这也是在 MINGW 中工作的唯一解决方案。

另一个编辑: 尝试了 CygWin 提供的所有解决方案。没有人工作。来自 Makefile 或直接在 CygWin 中。

(希望)最后一次编辑: 这是直接在 MINGW 中为我工作的命令:kubectl apply -f $(ls -m *.yaml | tr -d ' ')(@RicoChen 的解决方案) 当我尝试从 Makefile 运行它时:(在 MINGW 中使用 make kompose

.PHONY: kompose
kompose:
    kompose convert
    kubectl apply -f $(ls -m *.yaml | tr -d ' ')

由于某种原因它不起作用。

【问题讨论】:

  • 为什么需要grep -v /?您是否希望目录名称以.yaml 结尾?
  • @CharlesDuffy 好问题!不。我不期待。所以我想ls *.yaml -p | tr '\n' ',' 就足够了。谢谢!
  • “来自一个makefile”改变了很多东西很多;你应该把它标记为一个make问题(实际上,因为你已经得到了几个答案,所以这么晚才添加那个主要的细节可能是不合适的;最好接受任何在makefile之外正常工作的答案,然后问一个新问题这是关于 makefile 案例的明确说明)。
  • @CharlesDuffy 没有太大变化。直接运行此命令:来自 MINGW 的 kubectl apply -f "$(ls *.yaml -p | tr '\n' ',')" 会导致错误:error: the path "" does not exist。运行:kubectl apply -f "$(ls *.yaml -p | tr '\n' ',')" 导致相同的错误

标签: bash cmd makefile


【解决方案1】:

使用带有-exec 选项的find 命令应该相当容易:

find . -type f -iname "*.yaml" -exec kubectl apply -f {} \;

它的作用是找到当前目录下的所有*.yaml文件(递归),对于找到的每个文件,运行命令

kubectl apply -f file_found.yaml

[EDIT] 如果您确实想通过附加多个 .yaml 文件来运行 kubectl apply 一次,如您的问题所示,您可以这样做

kubectl apply -f $(ls -m *.yaml | tr -d ' ')

【讨论】:

  • 我可以一次性将所有以逗号分隔的文件传递给kubectl apply吗?
  • 这不是 OP 要求的,但如果 kubectl 实际上并不希望看到以逗号分隔的名称列表,也许这就是他们需要的。
  • 如果您查看kubernetes.io/docs/reference/kubectl/cheatsheet/#apply,使用 apply 命令的正确方法是分别在每个文件上运行或使用'-f filename1.yaml -f filename2.yaml ...',也就是说,每个文件名都需要“-f”。
  • @RicoChen,...感谢您在那里进行研究;我已经修改了我的答案的机制,显示如何为每个参数生成一个额外的-f
  • @RicoChen 查看此文档:kubernetes.io/docs/tasks/configure-pod-container/… 他们还支持逗号分隔字符串:kubectl apply -f frontend-service.yaml,redis-master-service.yaml,redis-slave-service.yaml,frontend-deployment.yaml,redis-master-deployment.yaml,redis-slave-deployment.yaml
【解决方案2】:

正是你所要求的

执行此操作的 shell 函数可能如下所示:

apply_files() {
  local IFS=,
  kubectl apply -f "$*,"
}

之后:

apply_files *.yaml

这是因为$* 将当前参数列表中的所有项目与$IFS 的第一个字符组合在一起,我们在函数中将其定义为逗号。


正确的 Kubectl 用法

apply_files() ){
  local -a args=( )
  for arg; do
    args+=( -f "$arg" )
  done
  kubectl apply "${args[@]}"
}

apply_files *.yaml

【讨论】:

  • 我可以在 Makefile 中创建函数吗(因为我是从 make 运行它 - 在问题中添加示例)
  • 这是可能的,但要困难得多,而且可能不值得在这里努力。
  • 尝试将您的脚本放入 .sh 文件并从 MINGW (./gen.sh) 运行它,第一个脚本导致与 Make:error: the path "" does not exist 相同的错误。第二个脚本导致其他错误:./gen.sh: line 1: syntax error near unexpected token )' ./gen.sh: line 1: apply_files() ){'
  • “意外令牌附近的语法错误”表示您正在使用 sh 而不是 bash 运行此代码。这并不奇怪,因为sh 是默认使用的shell。将其放入脚本时,以#!/usr/bin/env bash 开头,永远不要以sh scriptname 开头——如果您必须以这种方式开头,请使用bash scriptname。跨度>
  • @ET-CS, the path "" does not exist 听起来问题在于结尾的逗号。我把它放在那里是因为你的问题表明它是你声称你想要的命令的一部分。将"$*,"改成"$*",输出会是foo,bar,baz而不是foo,bar,baz,;如果没有最后的逗号,kubectl 将不会尝试读取名称为空的文件。
猜你喜欢
  • 1970-01-01
  • 2019-03-11
  • 2017-08-30
  • 2023-01-11
  • 2022-09-27
  • 1970-01-01
  • 1970-01-01
  • 2016-01-30
相关资源
最近更新 更多