马哥Linux培训课后作业(6)

2017-12-03|Categories: Magedu-training|

查询java命令来自于哪个rpm包

首先查询java命令是否已安装:

[liyang@centos7 ~]$ which java
/bin/java

然后查询命令所属的包:

[liyang@centos7 ~]$ rpm -q java
package java is not installed

单独查询时,居然提示java包未安装,换一种查询方式就是不同的结果:

[liyang@centos7 ~]$ rpm -qa | grep java
java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64
java-1.7.0-openjdk-1.7.0.141-2.6.10.5.el7.x86_64
javapackages-tools-3.4.1-11.el7.noarch
java-1.7.0-openjdk-headless-1.7.0.141-2.6.10.5.el7.x86_64
tzdata-java-2017b-1.el7.noarch
java-1.8.0-openjdk-headless-1.8.0.131-11.b12.el7.x86_64
python-javapackages-3.4.1-11.el7.noarch

可以看到,系统其实安装了很多java相关的包,但执行java命令具体是调用哪个文件呢?继续查询:

[liyang@centos7 ~]$ ls -l `which java`
lrwxrwxrwx. 1 root root 22 Nov  7 16:09 /bin/java -> /etc/alternatives/java

可以看到,java命令是调用/bin/java,而/bin/java是一个软链接,指向/etc/alternatives/java,这比较特殊,因为通常我们使用的命令的二进制文件是存放在$PATH变量中,而默认的$PATH变量并不包含/etc目录,为什么这里会例外?继续查看:

[liyang@centos7 ~]$ ll /etc/alternatives/java
lrwxrwxrwx. 1 root root 72 Nov  7 16:09 /etc/alternatives/java -> /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/jre/bin/java

这次终于看到指向的二进制文件了,那这个文件属于哪个包呢?继续查看:

[liyang@centos7 ~]$ rpm -qf $(readlink -f $(which java))
java-1.8.0-openjdk-headless-1.8.0.131-11.b12.el7.x86_64

因为前面的查询结果是一个长长的字符串,这里使用了readlink -f命令一步到位查询软链接最终指向的文件,节省输入时间。

这里还使用了$(command)这种语法,其实和`command`是等价的,都是执行命令展开,但$(command)允许多层嵌套。

虽然查询到了java命令所属的包,但还有一个疑问:为什么/bin/java要指向/etc/alternatives/java,而不是直接指向最终的/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/jre/bin/java?这里的关键词是alternatives,查询结果如下:

[liyang@centos7 ~]$ whatis alternatives
alternatives (8)     - maintain symbolic links determining default commands

[liyang@centos7 ~]$ whereis alternatives
alternatives: /usr/sbin/alternatives /etc/alternatives /usr/share/man/man8/alternatives.8.gz

看看man文件里的描述:

alternatives creates, removes, maintains and displays information about the symbolic links comprising the alternatives system.

首先解释alternatives命令的用途:用于创建、移除、维护、显示那些构成「替代系统 alternatives system」的软链接的信息。

It is possible for several programs fulfilling the same or similar functions to be installed on a single system at the same time. For example, many systems have several text editors installed at once. This gives choice to the users of a system, allowing each to use a different editor, if desired, but makes it difficult for a program to make a good choice of editor to invoke if the user has not specified a particular preference.

接下来说明为什么需要「替代系统」:针对某个特定类型的需求(例如文本编辑器),系统上可能同时安装多个功能相同或相似的软件包(例如edvivim),或者是同一个软件的不同版本(例如Vim7.4、Vim8),这可以方便不同用户自由选择,但对于应用程序来说,如果用户没有指定,该选择哪一个软件反而是一个麻烦,「替代系统」就是为了解决这个问题。

The alternatives system aims to solve this problem. A generic name in the filesystem is shared by all files providing interchangeable functionality. The alternatives system and the system administrator together determine which actual file is referenced by this generic name.

The generic name is not a direct symbolic link to the selected alternative. Instead, it is a symbolic link to a name in the alternatives directory, which in turn is a symbolic link to the actual file referenced. This is done so that the system administrator's changes can be confined within the /etc directory: the FHS (q.v.) gives reasons why this is a Good Thing.

然后解释「替代系统」的运行原理:首先建立一个「通用名称」,允许所有提供相同功能的软件使用,「替代系统」和系统管理员共同决定这个「通用名称」具体指向哪个软件。「通用名称」不会直接指向选定的「替代品 alternative」,相反,它软链接到「替代品目录 alternatives directory」中的一个「替代品名称」,这个名称再软链接指向实际的软件。这样做的目的是可以把系统管理员的更改限制在/etc目录,FHS解释了为什么这是一个好的选择。

When each package providing a file with a particular functionality is installed, changed or removed, alternatives is called to update information about that file in the alternatives system. alternatives is usually called from the %post or %pre scripts in RPM packages.

最后是实现细节:需要通过「替代系统」管理的软件会在rpm包里面编写脚本,在安装、更改、移除时调用alternatives命令更新「替代系统」中的信息。这些脚本通常位于%post或是%pre部分。对于前面查询到的java-1.8.0-openjdk-headless-1.8.0.131-11.b12.el7.x86_64包,它的脚本中包含如下alternatives命令:

[liyang@centos7 ~]$ rpm -q --scripts java-1.8.0-openjdk-headless | grep "alternatives"
alternatives \
  alternatives \
update-alternatives --install /usr/lib/jvm/jre-1.8.0-openjdk jre_1.8.0_openjdk /usr/lib/jvm/jre-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64 $PRIORITY  --family java-1.8.0-openjdk.x86_64 \
  alternatives --remove java /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/jre/bin/java
  alternatives --remove jre_openjdk /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/jre
  alternatives --remove jre_1.8.0 /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64/jre
  alternatives --remove jre_1.8.0_openjdk /usr/lib/jvm/jre-1.8.0-openjdk-1.8.0.131-11.b12.el7.x86_64

CentOS编译安装httpd,并启动服务

自动下载编译脚本

CentOS 6编译安装httpd 2.2,CentOS 7编译安装httpd 2.4。

#!/bin/bash
#
#===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== =====
# Filename:     auto_compile_httpd_by_liyang.sh
# Revision:     1.0
# Date:         2017-11-30
# Description:
# Author:       Li Yang
# Website:      https://liyang85.com
#===== ===== ===== ===== ===== ===== ===== ===== ===== ===== ===== =====

osVer=`cat /etc/centos-release | sed -nr 's/.*release ([0-9]+)\..*/\1/p'`

if [ `id -u` -eq 0 ]; then
    # install deps
    yum -y groupinstall "Development Tools"
    yum -y install apr-devel apr-util-devel openssl-devel pcre-devel lynx

    # make a dir to store source code
    srcDir="/src"
    if [ -d "${srcDir}" ]; then
        cd ${srcDir}
    else
        mkdir ${srcDir} && cd $_
    fi

    # download/compile httpd 2.2 in CentOS 6
    if [ "${osVer}" = 6 ]; then
        wget http://apache.spinellicreations.com//httpd/httpd-2.2.34.tar.bz2
        tar xf httpd-2.2.34.tar.bz2
        cd httpd-2.2.34
    fi

    # download/compile httpd 2.4 in CentOS 7
    if [ "${osVer}" = 7 ]; then
        wget http://apache.spinellicreations.com//httpd/httpd-2.4.29.tar.bz2
        tar xf httpd-2.4.29.tar.bz2
        cd httpd-2.4.29
    fi

    ./configure --prefix=/app/httpd --enable-ssl --enable-proxy-fcgi
    make && make install

    # config PATH
    cfgPath="/etc/profile.d/httpd.sh"
    cat >> ${cfgPath} <<- EOF
    pHttpd="/app/httpd/bin"
    export PATH="\${pHttpd}:\$PATH"
    EOF
    source ${cfgPath}

    # start httpd then check it if running
    apachectl start
    apachectl | grep --color=auto running
    echo
    curl -I localhost | grep --color=auto -i 'ok' \
        && echo -e '\nhttpd is running and can be accessed.\n' \
        || echo -e '\nhttpd is not running, \033[32mmaybe you need to disable SELinux and iptables.\033[0m\n'
else
    echo "Only root user can run this script."
fi

开机启动脚本/etc/init.d/httpd

#!/bin/bash
#
# httpd        Startup script for the Apache HTTP Server
#
# chkconfig: - 85 15
# description: The Apache HTTP Server is an efficient and extensible  \
#          server implementing the current HTTP standards.
# processname: httpd
# config: /app/httpd/conf
#
### BEGIN INIT INFO
# Provides: httpd
# Required-Start: $local_fs $remote_fs $network $named
# Required-Stop: $local_fs $remote_fs $network
# Should-Start: distcache
# Short-Description: start and stop Apache HTTP Server
# Description: The Apache HTTP Server is an extensible server
#  implementing the current HTTP standards.
### END INIT INFO

# Source function library.
. /etc/rc.d/init.d/functions

if [ -f /etc/sysconfig/httpd ]; then
        . /etc/sysconfig/httpd
fi

# Start httpd in the C locale by default.
HTTPD_LANG=${HTTPD_LANG-"C"}

# This will prevent initlog from swallowing up a pass-phrase prompt if
# mod_ssl needs a pass-phrase from the user.
INITLOG_ARGS=""

# Set HTTPD=/usr/sbin/httpd.worker in /etc/sysconfig/httpd to use a server
# with the thread-based "worker" MPM; BE WARNED that some modules may not
# work correctly with a thread-based MPM; notably PHP will refuse to start.

# Path to the apachectl script, server binary, and short-form for messages.
apachectl=/app/httpd/bin/apachectl
httpd=${HTTPD-/app/httpd/bin/httpd}
prog=httpd
pidfile=${PIDFILE-/app/httpd/logs/httpd.pid}
lockfile=${LOCKFILE-/var/lock/subsys/httpd}
RETVAL=0
STOP_TIMEOUT=${STOP_TIMEOUT-10}

# The semantics of these two functions differ from the way apachectl does
# things -- attempting to start while running is a failure, and shutdown
# when not running is also a failure.  So we just do it the way init scripts
# are expected to behave here.
start() {
        echo -n $"Starting $prog: "
        LANG=$HTTPD_LANG daemon --pidfile=${pidfile} $httpd $OPTIONS
        RETVAL=$?
        echo
        [ $RETVAL = 0 ] && touch ${lockfile}
        return $RETVAL
}

# When stopping httpd, a delay (of default 10 second) is required
# before SIGKILLing the httpd parent; this gives enough time for the
# httpd parent to SIGKILL any errant children.
stop() {
    status -p ${pidfile} $httpd > /dev/null
    if [[ $? = 0 ]]; then
        echo -n $"Stopping $prog: "
        killproc -p ${pidfile} -d ${STOP_TIMEOUT} $httpd
    else
        echo -n $"Stopping $prog: "
        success
    fi
    RETVAL=$?
    echo
    [ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}
}

reload() {
    echo -n $"Reloading $prog: "
    if ! LANG=$HTTPD_LANG $httpd $OPTIONS -t >&/dev/null; then
        RETVAL=6
        echo $"not reloading due to configuration syntax error"
        failure $"not reloading $httpd due to configuration syntax error"
    else
        # Force LSB behaviour from killproc
        LSB=1 killproc -p ${pidfile} $httpd -HUP
        RETVAL=$?
        if [ $RETVAL -eq 7 ]; then
            failure $"httpd shutdown"
        fi
    fi
    echo
}

# See how we were called.
case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
        status -p ${pidfile} $httpd
    RETVAL=$?
    ;;
  restart)
    stop
    start
    ;;
  condrestart|try-restart)
    if status -p ${pidfile} $httpd >&/dev/null; then
        stop
        start
    fi
    ;;
  force-reload|reload)
        reload
    ;;
  graceful|help|configtest|fullstatus)
    $apachectl $@
    RETVAL=$?
    ;;
  *)
    echo $"Usage: $prog {start|stop|restart|condrestart|try-restart|force-reload|reload|status|fullstatus|graceful|help|configtest}"
    RETVAL=2
esac

exit $RETVAL

备注:chmod +x之后,以上脚本可在CentOS 6正常工作。

从安装光盘解压启动脚本

以上脚本来自网络,也可以从系统安装光盘解压缩官方自带的脚本:

# use autofs to mount CentOS installation dvd
cd /misc/cd/Packages

# find the target file in the package
rpm2cpio httpd-2.2.15-59.el6.centos.x86_64.rpm \
    | cpio -tv | grep "init.d/httpd"

# view content of the target file then redirect it
rpm2cpio httpd-2.2.15-59.el6.centos.x86_64.rpm \
    | cpio -i --to-stdout ./etc/rc.d/init.d/httpd \
    > /etc/rc.d/init.d/httpd

当然,解压出来的脚本仍然需要根据编译设置修改。

设置httpd开机启动

chkconfig --add httpd
chkconfig httpd on
chkconfig --list httpd

Leave A Comment