Menu

目录

在容器中执行新命令

描述

lcrc exec命令用于正在运行的容器中运行一个新命令。新执行的命令将在容器的默认目录中运行。如果基础镜像指定了自定义目录,则将使用该目录。

用法

lcrc exec [OPTIONS] CONTAINER COMMAND [ARG...]

参数

exec命令支持参数参考下表。

表 1 exec命令参数列表

命令

参数

说明

exec

-d, –detach

后台运行命令

-e, –env

设置环境变量(备注:目前LCRD尚不使用此功能)

-H, –host

指定要连接的LCRD socket文件路径

-i, –interactive

没有连接,也要保持标准输入打开(备注:目前LCRD尚不使用此功能)

-t, –tty

分配伪终端(备注:目前LCRD尚不使用此功能)

约束限制

  • lcrc exec 不指定任何参数时,会默认使用-it参数, 表示分配一个伪终端,以交互式的方式进入容器
  • 当使用lcrc exec 执行脚本,在脚本中执行后台进程时,需使用nohup标志忽略SIGHUP信号。

    使用lcrc exec运行脚本,在脚本中运行后台进程需使用nohup标志。否则内核会在exec执行的进程(session首进程)退出时,向后台执行的进程发送SIGHUP信号,导致后台进程退出,出现僵尸进程。

  • lcrc exec 进入容器进程后,不能执行后台程序,否则会出现卡死现象。

    lcrc exec执行后台进程的方式如下:

    1. 使用lcrc exec进入容器终端,lcrc exec container_name bash
    2. 进入容器后,执行 script &
    3. 执行exit,导致终端卡死

      lcrc exec 进入容器后,执行后台程序卡住的原因为lcrc exec进入容器运行后台while1程序,当bash退出时,while1程序并不会退出,变为孤儿进程由1号
      进程接管,while1程序是由容器的初始bash进程fork &exec执行的,while1进程复制了bash进程的文件句柄,导致bash退出时,句柄并未完全关闭,导致
      console进程收不到句柄关闭事件,epoll_wait卡住,进程不退出。
      
  • lcrc exec 不能用后台方式执行,否则可能会出现卡死现象。

    lcrc exec后台执行的方式如下:

    使用**lcrc exec 脚本 & **的方式后台执行exec,如:lcrc exec container_name script & ,lcrc exec 后台执行,执行的脚本中不断cat某一文件,正常时在当前终端有输出,如果在当前终端执行回车操作,客户端会因读IO失败而退出读stdout的动作,使终端不再输出,服务端由于进程仍然在cat文件,会继续往fifo的buffer里写入数据,当缓存写满时,容器内进程会卡死在write动作上。

  • 轻量级容器使用exec执行带有管道操作的命令时,建议使用/bin/bash -c 方式执行该命令。

    典型应用场景:

    使用lcrc exec container_name -it ls /test | grep “xx” | wc -l,用于统计test目录下xx的文件个数,因exec执行的为”ls /test”,其输出通过管道进行grep、wc 处理。exec执行的为”ls /test”的输出会换行,再针对该输出进行处理时,结果有误。

    原因:使用exec 执行ls /test,输出带有换行,针对该输出进行“| grep “xx” | wc -l“,处理结果为2(两行)

    [root@localhost ~]# lcrc exec  -it container ls /test
    xx    xx10  xx12  xx14  xx3   xx5   xx7   xx9
    xx1   xx11  xx13  xx2   xx4   xx6   xx8
    [root@localhost ~]#
    

    建议处理方式:使用run/exec执行带有管道操作的命令时,使用/bin/bash -c 执行命令,在容器中执行管道操作。

    [root@localhost ~]# lcrc exec  -it container  /bin/sh -c "ls /test | grep "xx" | wc -l"
    15
    [root@localhost ~]#
    
  • 禁止使用echo的方式向exec命令的stdin输入数据,会导致客户端卡死。应该直接将echo的值作为命令行参数传给容器

    [root@localhost ~]# echo ls | lcrc exec 38 /bin/sh
        
        
    ^C
    [root@localhost ~]# 
    

    上述命令可能出现客户端卡死现象,这是由于上述命令相当于往stdin输入ls,随后EOF被读取,客户端不再发送数据,等待服务端退出,但是服务端无法区分客户端是否需要继续发送数据,因而服务端卡在read数据上,最终导致双方均卡死。

    正确的执行方式为:

    [root@localhost ~]# lcrc exec 38 ls
    bin   dev   etc   home  proc  root  sys   tmp   usr   var
    

示例

在运行中的容器中,执行echo命令

$ lcrc exec c75284634bee echo "hello,world"
hello,world