折腾了半天,还是想不通,为什么用execlcall启动的dash就变成僵尸了。
下面是一个最小的测试用例——我只是 fork 一个孩子,复制 std [in,out,err]描述符,然后启动sh。
#include <cstdio>
#include <fcntl.h>
#include <cstring>
#include <stdlib.h>
#include <cerrno>
#include <unistd.h>
int main() {
int pipefd[2];
enum {
STDOUT_TERM = 0,
STDIN_TERM = 1
};
if (pipe(pipefd) == -1) { //make a pipe
perror("pipe");
return 0;
}
pid_t pid = fork();
if (pid == 0)
{// Child
dup2(pipefd[STDIN_TERM], STDIN_FILENO);
dup2(pipefd[STDOUT_TERM], STDOUT_FILENO);
dup2(pipefd[STDOUT_TERM], STDERR_FILENO);
execl("/bin/sh","sh", (char*)NULL);
// Nothing below this line should be executed by child process. If so, …Run Code Online (Sandbox Code Playgroud) 命令
find /tmp -name 'core*' -type f -print0 | xargs -0
Run Code Online (Sandbox Code Playgroud)
在 Linux 上工作正常,但xargs -0在 Solaris 上选项不合法
xargsSolaris 10的等效选项 ( ? )是什么
第二个问题:
是否可以更改语法:
find /tmp -name 'core*' -type f -print0 | xargs -0
Run Code Online (Sandbox Code Playgroud)
因此它将适用于操作系统 - Linux 和 Solaris
我在我的solaris 10机器上尝试:
find /tmp -name 'core*' -type f -print0 | xargs -0
xargs: illegal option -- 0
xargs: Usage: xargs: [-t] [-p] [-e[eofstr]] [-E eofstr] [-I replstr] [-i[replstr]] [-L #] [-l[#]] [-n # [-x]] [-s size] [cmd [args …Run Code Online (Sandbox Code Playgroud) 来自 bash 手册
执行
Run Code Online (Sandbox Code Playgroud)exec [-cl] [-a name] [command [arguments]]如果提供了命令,它将替换外壳而不创建新进程。如果提供了 -l 选项,shell 会在传递给 command 的第零个参数的开头放置一个破折号。这就是登录程序所做的。-c 选项导致命令在空环境下执行。
没有-c选项,command [arguments]运行的执行环境是什么?
和运行前原shell进程中的执行环境一样exec command [arguments]吗?
原始shell进程中的执行环境不仅包含环境变量,还包含包括非环境变量在内的所有shell变量。commandinexec command运行所在的执行环境是否也包含原始shell进程中的非环境变量?
你能举一些例子来说明这一点吗?
我想将所有调试输出设置到日志文件中。所以我检查了命令行 - bash: set -x messages to file | 询问 Ubuntu并按照说明进行操作。
测试脚本:
#!/bin/bash
exec 5 >/var/log/test.log
export BASH_XTRACEFD=5
main(){
set -x
echo hello
set +x
}
main
Run Code Online (Sandbox Code Playgroud)
跑步:
./test-script
Run Code Online (Sandbox Code Playgroud)
返回:
exec: 5: not found
Run Code Online (Sandbox Code Playgroud)
手册显示你也可以做到这一点,那么为什么上面的方法不起作用呢?
我正在教授操作系统课程,并试图围绕创建新进程的fork/execve技术进行思考。
我目前的理解是,fork 会完整复制旧进程,建立新的 PID 和父/子关系,但除此之外几乎没有其他作用。
另一方面,子进程创建后,它运行 execve 以用新进程替换其大部分内存。例如,程序代码、栈、堆被完全替换,作为一个新程序从头开始。
但并不是所有的东西都在新流程中被取代。子进程继承文件描述符(允许在 execve 之前设置管道)、进程 ID (PID) 和用户 ID (UID) 以及一些权限(手册页)。
我想没有被 execve 调用替换的属性的完整列表很长,但是是否还有其他关键属性,例如我上面提到的那些我遗漏的?
当 C 程序被 kernel\xe2\x80\x94by 执行时execve(),
在哪里调用在调用 main 函数之前调用的execve()特殊启动例程?crt0
execve()main函数在哪里调用?
我在https://elixir.bootlin.com/linux/latest/source/fs/exec.c中找不到它们。
\n\n从理解Linux内核开始,execve()内部寻找一个可以加载可执行文件的linux_binfmt对象并调用其方法来加载,同时还加载动态链接器来加载和链接可执行文件所使用的共享库。但书中没有说明如何从可执行文件中调用启动例程和程序的 then 。load_binary()load_binary()execve()crt0main()
谢谢。
\n我正在关注这个问题,尽管这里的一些文件名在文件名开头包含破折号。这被解释为 的附加选项cp。
在另一个问题(关于 ServerFault)之后,我尝试将命令更改为:
shuf -zn8 -e *.jpg | xargs -0 cp -vt -- {} target/
Run Code Online (Sandbox Code Playgroud)
或者
shuf -zn8 -e *.jpg -exec cp -vt -- {} target/
Run Code Online (Sandbox Code Playgroud)
无济于事。如何处理-文件名的开头部分?
我正在 AIX 7.2 上运行 ksh 脚本。
在调试模式下,我想将所有脚本执行的操作重定向到 brkpt 文件。
该脚本还登录另一个应用程序,因此使用密码(假设“pw123_”)
exec > $brkpt_file 2>&1
set -xv
dsmadmc -id=admin -pa=pw123_ q pr
Run Code Online (Sandbox Code Playgroud)
重定向工作正常,但我想用“***”替换密码字符串,以便它在 brkpt 文件中永远不可见。
这在命令行上工作得很好:
echo "dsmadmc -id=admin -pa=pw123_ q pr" | sed "s/-pa=[[:graph:]]* /-pa=*** /g"
result
dsmadmc -id=admin -pa=*** q pr
Run Code Online (Sandbox Code Playgroud)
但是一旦我将这个“sed”与“exec”结合使用:
a)输出不再重定向到文件,而是在屏幕上
b)密码字符串不会被替换
exec | sed 's/-pa.*=[[:graph:]]* /pa=*** /g' > $brkpt_file 2>&1
set-xv
dsmadmc -id=admin -pa=pw123_ q pr
result
+ dsmadmc -id=admin -pa=pw123_ q pr
+ ... other stuff of script
Run Code Online (Sandbox Code Playgroud)
如何获取 brkpt 中的所有脚本内容并隐藏密码?
我正在为 AWS EC2 编写一个 Terraform 模块,其中涉及在用户数据部分执行 bash。当我开发时,我编写的脚本中遇到了问题,但 AWS 和 Terraform 都没有提供任何错误日志,直到我在 AWS 支持论坛中找到这一行:
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
Run Code Online (Sandbox Code Playgroud)
user_data这一行成功写入了脚本执行的所有输出/var/log/user-data.log,但我不理解整行。我知道exec >将所有输出写入一个文件,在这种情况下>(..),但我不明白为什么使用它tee或需要那里的管道。
我制作了一个简单的脚本,每分钟执行一个命令:
#!/usr/bin/env sh
while true; do
exec "$@"
sleep 60
done
Run Code Online (Sandbox Code Playgroud)
这个想法是把它作为一个Docker 入口点,让我能够运行 Laravel 调度程序。但在构建图像之前,我想对其进行测试:
$ ./entrypoint/entrypoint_cron.sh echo "Hello"
Hello
Run Code Online (Sandbox Code Playgroud)
但该命令只执行一次。为什么?如何使参数中提供的命令连续循环运行,直到我用Ctrl+终止它C?
exec ×10
bash ×3
linux ×3
xargs ×2
api ×1
c ×1
c++ ×1
capabilities ×1
command-line ×1
cp ×1
find ×1
ksh ×1
password ×1
process ×1
sed ×1
shell ×1
shell-script ×1
solaris ×1
system-calls ×1