我有一个RPM规范文件,建立在带有rpmbuild的rhel7上,我想用脚本定义版本。
我在这里读到 http://www.techrepublic.com/article/rpmproc-spec-file/,我可以这样做:
%define version 1.2
Version: %{version}
这里RPM规范文件 - 是否可以动态填充一个spec文件变量,我可以用脚本定义:
%define whoami %(cmd)
所以我尝试在我的规范文件中执行此操作:
%define version %(echo "$(sed -n 's|^[ ]*appVersion = "(.*)"|1|p' /fullfilepath/values.txt | sed 's/^(.*)-.*$/1/')")
Version: %{version} **Line 23**
但我得到一个
error: line 23: Empty tag: Version:
到目前为止,我已经测试过的东西:
%define version %(echo "12") --basic script works ok, version becomes 12
//As a command straight in terminal
$ echo "$(sed -n 's|^[ ]*appVersion = "(.*)"|1|p' /fullfilepath/values.txt | sed 's/^(.*)-.*$/1/')"
//returns 1.2
这些工作得很好,所以我不知道是什么导致它失败。 任何想法,当我在规范文件中定义标签中调用相同的东西时,会导致它失败?
更新
我尝试将文件名替换为实际值,因此看起来像这样
echo "$(sed -n 's|^[ ]*appVersion = "(.*)"|1|p' <<< "appVersion = "1.2-SNAPSHOT"" | sed 's/^(.*)-.*$/1/')"
这在终端中调用时有效,但作为
%(echo "$(sed -n 's|^[ ]*appVersion = "(.*)"|1|p' <<< "appVersion = "1.2-SNAPSHOT"" | sed 's/^(.*)-.*$/1/')")
但我仍然得到
Empty tag: Version: Error
更新 2
我测试了一个更复杂的命令,然后echo "12"
:
%define version %(echo "$(git log -1 | grep commit | awk -F"commit " '{print $2}' | cut -c1-8)")
这也行得通!使版本成为提交哈希的前 7 位数字。
更新 3
谜团还在继续,我做了一个测试来检查是否是 sed 命令是原因,但以下命令给了我 1.2 作为版本
%define version %(echo "$( sed 's/.*= //' <<< "appVersion = 1.2" )")
如果这个命令有效但不是我的第一个命令,那么它必须与我的第一个命令中的某些内容一起使用,该命令仅在直接在终端中而不是在 %(cmd( 中调用时才有效。越来越近!
更新 4
好的,所以我似乎已经隔离了它必须是什么,好奇,看起来它可能是 rpmbuild 不喜欢的-n
或s| | 1 |p
语法。我做了一个更简单的原始版本。看看吧:
#Error, doesn`t set version to 1.2
%define version %(echo "$( sed -n 's|^.*-(-*)|1|p' <<< "foo-1.2" )")
#Works ok! sets version to 1.2
%define version %(echo "$( sed 's/.*= //' <<< "appVersion = 1.2" )")
不幸的是,尽管我认为我无法再做隔离并找出问题所在。在第二个命令的样式中使用 sed 没有错,但对于为什么第一个命令不起作用仍然非常有趣。
更新 5
我发现在 %(( 中使用规范文件和 rpmbuild 中的任何脚本时,这里存在一些深层次的问题。我尝试使用 awk 只是为了看看会发生什么,它也坏了!这比我最初想的要深得多,就像发现了一个阴谋:
#In terminal it prints 1.2-SNAPSHOT, but in Spec it's an error
%define version %(echo "$(awk '/appVersion /{ print $3 }' <<< "appVersion = "1.2-SNAPSHOT"" | tr -d ")")
sh: -c: line 0: unexpected EOF while looking for matching `)'
sh: -c: line 1: syntax error: unexpected end of file
error: line 23: Empty tag: Version:
更新 6
对大家来说是好消息和坏消息,我发现 rpm 似乎在后台做一些自己的工作,并没有显示它的作用,我终于找到了一个命令,当通过 rpm 调用时给出不同的值:
%define version %(echo "$(awk '/midonetVersion /{ print $3 }' <<< "midonetVersion = "5.1-SNAPSHOT"")")
#In terminal it echos "5.1-SNAPSHOT" (literally wrapped in "" )
#When in spec it set version to 5.1-SNAPSHOT , rpmbuild is removing the ""
所以现在我做了一个调整,称之为:
#echos "5.1 in terminal and sets version to 5.1 in spec
%define version %(echo "$(awk '/appVersion /{ print $3 }' <<< "appVersion = "1.2-SNAPSHOT"")"| cut -d'-' -f1)
因此,从这个来看,我认为可能有类似的幕后解析我的第一个 rpm sed 命令的结果。我们会有我们的方式 rpm!
最终更新
使用rpm 休战,我将改用以下命令:
%define version %(echo "$(awk '/ appVersion =/{ print $3 }' /filepath/values.txt" | sed 's/"//g' | cut -d'-' -f1)
它与我的第一个命令执行相同的操作,并在规范文件中正确设置版本号。如果有人猜测为什么第一个命令无法运行,我会很高兴阅读它。和平!
你必须有一个调用 rpmbuild 命令的 shell 脚本。您可以使用该脚本来计算版本(或者就此而言,您尝试在 rpm 规范文件中使用的任何命令(。
更改您的原始代码,
%define version %(echo "$(sed -n 's|^[ ]*appVersion = "(.*)"|1|p' /fullfilepath/values.txt | sed 's/^(.*)-.*$/1/')")
Version: %{version}
自
%define version _VERSION_
Version: %{version}
和 sed VERSION 到它在调用 rpmbuild 的 shell 脚本中的计算值(在调用 rpmbuild 之前(。将实际规范内容转储到某个文件后,将生成的文件传递给同一 shell 脚本中的 rpmbuild。
以下是步骤摘要:
假设您有一个调用 rpmbuild 的 builder.sh shell 脚本,请执行以下步骤:
- 更新您的规范文件以具有 VERSION 占位符字符串/宏,如上所示
- 将当前转速规范文件移至 my_package_template.spec
- 在 builder.sh 中,运行命令以获取版本并将版本保存到变量
- 对 my_package_template.spec 文件使用 sed 命令将 VERSION 替换为此计算版本,并将 sed 输出保存到 my_package.spec
- 将 my_package.spec 传递给 rpmbuild 命令。
重复步骤 1、3 和 4 以替换 spec 文件中任何其他 shell 命令的使用。
我会做一个包装脚本。这使您可以决定它是常规版本还是开发版本等。然后,您可以使用--define
选项传递变量 - 有关更多选项,请参阅此问题。
为了回应@Herrgott的评论"如果你在规范中%define
它并尝试用--define
重新定义它不会覆盖它"(注释中不能有换行符( - 你可以设置一个同名的"_override
"变量与--define
。
%if 0%{?val_override:1}
%define val %{val_override}
%else
%define val whatever
%endif
Necro,但我们开始了。
首先,所有都必须转义,因此您需要将它们全部切换到 .
\
其次,当您调用:
%define version %(echo "$(sed -n 's|^[ ]*appVersion = "(.*)"|1|p' /fullfilepath/values.txt | sed 's/^(.*)-.*$/1/')")
您实际上是在调用一个子shell,用于打印要运行的命令的文本。 但是,当您使用:
Version: %{version}
您需要%{version}
计算为就地字符串,而不是命令才能获取它。 可能您只需要删除echo
部分,这也简化了命令。
如果我没记错的话,我相信您在 sed
命令中使用了仅可用于扩展正则表达式的正则表达式语法,因此您需要它的-E
选项。 但是,您使用第一个 sed
命令所做的是从文件中提取appVersion = "
到最后一"
后的所有内容,然后尝试删除该行上最后一个-
之后的所有内容。 假设您确实希望在第一个版本号之前-
部分,这更容易通过利用K
运算符仅返回匹配内容的grep -Po
来实现。
%define version %(grep -P '^[ ]*appVersion = "\K([^"-]+)' /fullfilepath/values.txt)
现在,%{version}
设置为运行分析命令时返回的值,而不是命令本身。 如果解析有任何问题,它将投注设置为 %{nil}
(空(。
但是,您需要记住,/fullfilepath/values.txt
路径是调用rpmbuild
或rpmspec
时的路径。 如果运行它的主机系统没有恰好/fullfilepath/values.txt
的文件,那么它将无法找到要解析的文件。
如果您确实需要将其设置为要运行的命令而不是运行它的值,则可以省略周围的%()
,而只需将其设置为
%define version grep -P '^[ ]*appVersion = "\K([^"-]+)' /fullfilepath/values.txt