Bash shell脚本在通过stdin传递给LXC容器时不按顺序执行
我将以下简单的
shell脚本传递给LXC容器上的bash:
apt-get update apt-get install postgresql -y sudo -u postgres psql -c 'create database dvdrental;' 我用来运行它的实际命令是: cat sample.sh | lxc-attach -n test-container -- /bin/bash 我之所以这样做,而不是将脚本上传到容器中并执行这种方式,这只是我们正在构建的一个更复杂的应用程序的概念证明,它必须通过stdin接受命令并运行它们在容器中. 它似乎工作得很好,除了一件事.当postgresql仍在安装时,它移动到psql命令,即 [...] Get:21 http://archive.ubuntu.com/ubuntu/ trusty/main ssl-cert all 1.0.33 [16.6 kB] Get:22 http://archive.ubuntu.com/ubuntu/ trusty-updates/main postgresql-common all 154ubuntu1 [103 kB] Get:23 http://archive.ubuntu.com/ubuntu/ trusty-updates/main postgresql-9.3 amd64 9.3.10-0ubuntu0.14.04 [2,669 kB] Get:24 http://archive.ubuntu.com/ubuntu/ trusty-updates/main postgresql all 9.3+154ubuntu1 [5,038 B] Fetched 5,834 kB in 28s (207 kB/s) Preconfiguring packages ... sudo -u postgres psql -c 'create database dvdrental;' Selecting previously unselected package libroken18-heimdal:amd64. (Reading database ... 14599 files and directories currently installed.) Preparing to unpack .../libroken18-heimdal_1.6~git20131207+dfsg-1ubuntu1.1_amd64.deb ... Unpacking libroken18-heimdal:amd64 (1.6~git20131207+dfsg-1ubuntu1.1) ... Selecting previously unselected package libasn1-8-heimdal:amd64. [...] 注意存在sudo -u postgres psql -c’create database dvdrental;’在输出中间的行.有趣的是,它总是在apt-get命令的下载部分完成后立即出现…… 有人知道是什么原因引起的吗?
哦,这是一个有趣的.
简短的回答:它发生在那里因为apt(或它的东西)在执行中的那一点读取stdin,并且它读取脚本的剩余行,因为那是在那时仍然在stdin中.简短的修复:在apt-get安装行的末尾放置< / dev / null,然后继续你的一天. 答案很长(严肃地说,这是一个大枪):从运行过程的角度来看,stdin / stdout / stderr并没有什么特别之处.它们只是文件描述符,文件描述符在进程分叉时在进程之间共享.那么,会发生什么(或多或少): 如果在整个过程中没有任何东西干扰stdin(在这种情况下它没有),那么从将管道的读取器端作为stdin的那个分叉的每个进程也将具有完全相同的文件描述符,附加到相同的管道,其中包含sample.sh的内容,作为其标准输入.从该文件描述符读取的任何进程现在都将消耗读取的字节,并且从该文件描述符读取的其他进程将不会获得这些特定字节.仔细注意这一点;你会再次看到这个材料. 毫无疑问,“共享标准”问题的解决方案是停止传递stdin,就像在兄弟会派对上一样.既然你无法阻止fork(2)自动给每个人提供相同的文件描述符,那么你需要告诉bash,让apt-get(以及其他任何从那个甜蜜的管道中非法啜饮的东西)给别的东西相反.最简单的事情是/ dev / null – 永远忠实,永不满足的所有“戴夫不在这里,男人”的喜悦.那是“输入重定向”的域,这是< / dev / null的作用 - 它说,“嘿bash,在你执行apt-get之前,用文件描述符换出stdin(文件描述符0)你从打开/ dev / null获得“. 读者练习,完成:尝试在apt-get install命令之后输入< / dev / zero,并解释为什么会发生什么. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |