在容器中执行新命令

描述

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

用法

  1. isula exec [OPTIONS] CONTAINER COMMAND [ARG...]

参数

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

表 1 exec命令参数列表

命令

参数

说明

exec

-d, —detach

后台运行命令

-e, —env

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

-H, —host

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

-i, —interactive

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

-t, —tty

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

-u, —user

指定用户登录容器执行命令

约束限制

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

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

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

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

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

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

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

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

    典型应用场景:

    使用isula 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(两行)

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

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

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

    ``` [root@localhost ~]# echo ls | isula exec 38 /bin/sh

  1. ^C
  2. [root@localhost ~]#
  3. ```
  4. 上述命令可能出现客户端卡死现象,这是由于上述命令相当于往stdin输入ls,随后EOF被读取,客户端不再发送数据,等待服务端退出,但是服务端无法区分客户端是否需要继续发送数据,因而服务端卡在read数据上,最终导致双方均卡死。
  5. 正确的执行方式为:
  6. ```
  7. [root@localhost ~]# isula exec 38 ls
  8. bin dev etc home proc root sys tmp usr var
  9. ```

示例

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

  1. $ isula exec c75284634bee echo "hello,world"
  2. hello,world