【问题标题】:How to run and interact with a script from within an RPM?如何在 RPM 中运行脚本并与之交互?
【发布时间】:2016-04-10 11:21:52
【问题描述】:

我正在构建一个需要以 root 身份运行 bash 脚本的 RPM。

规范文件的%install 节是:

%install

cp %{SOURCE1} %{SOURCE2} %{_tmppath}/%{name}-%{version}-%{release}
cd %{_tmppath}/%{name}-%{version}-%{release}
chmod u+x %{installscript}
sudo ./%{installscript}

%{installscript} 是使用 sudo 以 root 身份运行的脚本。

rpmbuild 执行 %{installscript} 并创建 RPM(没有问题)。

然而,当我安装 RPM 时:

$ sudo rpm -Uvh $rpmpath
Preparing...                ########################################### [100%]
   1:tty-cap ########################################### [100%]
$

%{installscript} 脚​​本未执行。

我尝试通过将脚本调用移动到%post 节来更改规范文件:

%install

cp %{SOURCE1} %{SOURCE2} %{_tmppath}/%{name}-%{version}-%{release}
cd %{_tmppath}/%{name}-%{version}-%{release}

%post

chmod u+x %{installscript}
sudo ./%{installscript}

但是%post 似乎什么也没做。

如何打包一个在安装后执行脚本的 RPM?


编辑 1:

在查看了下面有用的 cmets 之后,这里有一个带有 %post 节的规范文件,它在 RPM 安装期间实际执行。
但是,脚本 %{installscript} 不与用户交互(就像从 shell 运行时那样),但似乎在没有用户交互的情况下接受其所有默认值。
我应该更改什么以使脚本能够与rpm 命令用户交互?

$ cat ~/RPMBUILD/SPECS/demo.spec
#
# %_topdir and %_tmppath are defined in  ~/.rpmmacros

%define name tty-cap
%define version 5.2
%define release 1
%define buildroot %{_tmppath}/%{name}-%{version}-%{release}

%define tarversion tty-5.2.0-00-70270
%define tarfile %{tarversion}.tar
%define installscript tty.install.sh

Name:           %{name}
Version:        %{version}
Release:        %{release}
BuildArch:      noarch
Summary:        Bla
License:        Proprietary
Source1:        %{installscript}
Source2:        tty-5.2.0-00-70270.tar
Prefix:         /opt/Intellinx/TTYCapture
BuildRoot:      %{_builddir}/%{name}-root

%description
Demonstration RPM

%prep

%build

%install

cp %{SOURCE1} %{SOURCE2} %{_tmppath}/%{name}-%{version}-%{release}
cd %{_tmppath}/%{name}-%{version}-%{release}

%clean
[ ${RPM_BUILD_ROOT} != "/" ] && rm -rf ${RPM_BUILD_ROOT}

%post
echo ">>> Inside post <<<"
chmod u+x %{installscript}
./%{installscript}

%files

%define tmp /
%{tmp}/%{tarfile}
%{tmp}/%{installscript}

$ rpmbuild -v -bb  ~/RPMBUILD/SPECS/demo.spec
Executing(%prep): /bin/sh -e /home/ronbarak/RPMBUILD/tmp/rpm-tmp.oEOM10
+ umask 022
+ cd /home/ronbarak/RPMBUILD/BUILD
+ LANG=C
+ export LANG
+ unset DISPLAY
+ exit 0
Executing(%build): /bin/sh -e /home/ronbarak/RPMBUILD/tmp/rpm-tmp.qQFuTA
+ umask 022
+ cd /home/ronbarak/RPMBUILD/BUILD
+ LANG=C
+ export LANG
+ unset DISPLAY
+ exit 0
Executing(%install): /bin/sh -e /home/ronbarak/RPMBUILD/tmp/rpm-tmp.8rTMLa
+ umask 022
+ cd /home/ronbarak/RPMBUILD/BUILD
+ '[' /home/ronbarak/RPMBUILD/tmp/tty-cap-5.2-1 '!=' / ']'
+ rm -rf /home/ronbarak/RPMBUILD/tmp/tty-cap-5.2-1
++ dirname /home/ronbarak/RPMBUILD/tmp/tty-cap-5.2-1
+ mkdir -p /home/ronbarak/RPMBUILD/tmp
+ mkdir /home/ronbarak/RPMBUILD/tmp/tty-cap-5.2-1
+ LANG=C
+ export LANG
+ unset DISPLAY
+ cp /home/ronbarak/RPMBUILD/SOURCES/tty.install.sh /home/ronbarak/RPMBUILD/SOURCES/tty-5.2.0-00-70270.tar /home/ronbarak/RPMBUILD/tmp/tty-cap-5.2-1
+ cd /home/ronbarak/RPMBUILD/tmp/tty-cap-5.2-1
+ /usr/lib/rpm/check-buildroot
+ /usr/lib/rpm/redhat/brp-compress
+ /usr/lib/rpm/redhat/brp-strip /usr/bin/strip
+ /usr/lib/rpm/redhat/brp-strip-static-archive /usr/bin/strip
+ /usr/lib/rpm/redhat/brp-strip-comment-note /usr/bin/strip /usr/bin/objdump
+ /usr/lib/rpm/brp-python-bytecompile
+ /usr/lib/rpm/redhat/brp-python-hardlink
+ /usr/lib/rpm/redhat/brp-java-repack-jars
Processing files: tty-cap-5.2-1.noarch
Requires(interp): /bin/sh
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Requires(post): /bin/sh
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/ronbarak/RPMBUILD/tmp/tty-cap-5.2-1
Wrote: /home/ronbarak/RPMBUILD/RPMS/noarch/tty-cap-5.2-1.noarch.rpm
Executing(%clean): /bin/sh -e /home/ronbarak/RPMBUILD/tmp/rpm-tmp.Yag9bm
+ umask 022
+ cd /home/ronbarak/RPMBUILD/BUILD
+ '[' /home/ronbarak/RPMBUILD/tmp/tty-cap-5.2-1 '!=' / ']'
+ rm -rf /home/ronbarak/RPMBUILD/tmp/tty-cap-5.2-1
+ exit 0

$ sudo rpm -Uvh /home/ronbarak/RPMBUILD/RPMS/noarch/tty-cap-5.2-1.noarch.rpm
Preparing...                ########################################### [100%]
   1:tty-cap                ########################################### [100%]
>>> Inside post <<<

###### Starting tty capturing installation ######


Specify installation directory full path [/opt/Intellinx/TTYCapture]:
/opt/Intellinx/TTYCapture already exists. continue installation? (y/n) [y]
Extracting archive tty-5*.* ...

Please specify TTY sensor owner user [ronbarak]:
TTY sensor will be accessible by user 'ronbarak' in group 'ronbarak'

Specify sensor working directory full path [/opt/Intellinx/TTYCapture/work]:

Specify sensor listening port [1024-65000] [8888]:

Do you want to register the sensor service? (y/n) [n]
Server gxttySensorService is not register as a daemon

Executing default user shell (y/n) [y]

TTY capturing has been installed successfully.

【问题讨论】:

  • 正如我在 OP @Cyrus 中写的,the %post doesn't seem to do anything. 我什至尝试从 %post 执行 lspwd,但它们没有被执行。也许您可以在我的%post 中指出我做错了什么?
  • 顺便说一句:我建议在您的 rpm 中删除 sudo
  • rpmbuild 运行%build 规则,而%install 在安装包时运行。也许您忽略了将脚本添加到复制到 BUILDROOT 目录下的文件中(实际上显示的规范文件片段中没有足够的信息来提供更好的建议)。
  • 根据您的@Thomas 评论,我将 Edit 1 添加到 OP。该脚本现在正在从 %post 执行,但现在出现了一个新问题:该脚本不与 rpm 命令用户交互(它的行为就像为每个问题按下了 )!

标签: bash rpm rpmbuild rpm-spec


【解决方案1】:

您在这里混合了几个概念。所以让 make 退后一步。

%prep 部分,您应该解压缩您的%{SOURCE0} 并应用补丁(如果有)。通常这样做

%setup -q

但是,如果您愿意,您可以手动提取它。有关此宏的更多信息,请参阅http://www.rpm.org/max-rpm/s1-rpm-inside-macros.html

%build 部分,您通常将源代码编译成二进制文件。如果您使用解释型语言或您的 tar 包含已编译的二进制文件,则可能为空。

%install 部分,您应该将文件复制到%{buildroot} 并在那里创建将放在包中的结构。例如。 %{buildroot}/etc/yourconfig%{buildroot}/usr/bin/yourcommand 等。你可以在那里运行任何你想要的脚本,但请记住它只在构建时间运行。 IE。仅在您的机器(或构建系统)上。这旨在创建自动生成的文件(例如,来自源代码的库文档)。

然后你有部分%post 在安装包后在用户机器上运行。并且所有文件都安装在最终路径中。不在 buildroot 中。一开始你被改为/,所以你需要在那个用户机器上指定完整路径。

所以在你的情况下,它可能看起来像:

%install
mkdir -p %{buildroot}%{_bindir}
cp -a %{installscript} %{buildroot}%{_bindir}/
chmod a+x %{buildroot}%{_bindir}/%{installscript}

%files
%{_bindir}/%{installscript}

%post
%{_bindir}%{installscript}

服务器说明:

  1. %post部分在root下执行,所以不需要sudo。

  2. 强烈建议不要运行交互式脚本。 RPM 被设计为非交互的,并且周围的每个实用程序都假定在包安装期间没有交互(例如 PackageKit、Spacewalk 等)。所以迟早你会得到一些补偿。说用户在安装后手动运行某些命令(或使用 Ansible 或 Puppet 自动执行)会更安全。

【讨论】:

  • 感谢您的回答@msuchy。您能否评论一下我的 Edit 1 问题,即 - 脚本从 %post 运行,但不与 rpm 命令用户交互?
  • 因为那里的路径错误。你不能在那里使用相对路径。它不是在 rpmbuild 期间运行,而是在 'rpm -i' 或 'rpm -U' 期间运行。
  • 如果路径错误,脚本不会运行失败吗?正如我在Edit 1 中指出的那样,脚本确实运行,它只是不与用户交互。
  • 那是因为stdin被rpm关闭了。您可以通过执行“exec 0/tty”将标准输入分配回 tty。但你真的不应该这样做。我不应该告诉你。 :)
猜你喜欢
  • 1970-01-01
  • 2011-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-18
  • 2012-05-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多