为什么 bash 不打印 PS1 变量?
Why bash not printing PS1 variable?
我想创建远程 bash(通过 tcp 套接字),我写了这段代码:
// servfd is descriptor to server socket
int sockfd = accept(servfd,&addr,sizeof(addr));
dup2(sockfd,fileno(stdin));
dup2(sockfd,fileno(stdout));
dup2(sockfd,fileno(stderr));
setenv("PS1","# ",1);
execl("/system/bin/sh","sh",NULL);
并且提示没有打印到套接字,但是当我发送命令等时:'echo test'它正在工作但没有提示打印。
我找到了必须使用的解决方案 /dev/ptmx
再次编辑:我是愚蠢的。问题是 shell 不是交互式的,因为 std(in|out|err)
不再是 ttys。使用
execl("/system/bin/sh", "sh", "-i", "NULL");
// along with the fork dance from below if you want to continue with the main
// program after this
强制 mksh
进行交互,在这种情况下,它应该每次都向 stderr
打印提示。这也将使 mksh
解释 ~/.mkshrc
,其中可能设置了 PS1
。如果未在此处设置,您仍然需要导出 PS1
,并且 system()
的问题仍然存在。如果设置在那里,
system("sh -i");
旧的,可能已过时的答案部分:
编辑:这里的工作比我最初怀疑的要多一些。 system()
在到达其子 shell 的过程中丢弃环境变量。这与它 运行s(在这种情况下)
execl("/bin/sh", "sh", "-c", "sh", NULL);
(也就是说,运行宁sh -c sh
export
ed PS1
也可以重现)。我不太清楚为什么 sh -c sh
丢弃 PS1
;它不会对其他环境变量执行此操作。
在这种情况下,可以通过使用 fork
和 exec
来模仿 system()
调用而不会产生这种效果,如下面的代码所示。但是,PS1
仍需要 export
编辑才能让子进程看到它。
所以,最有可能的原因是 PS1
没有 export
ed 并且 system()
丢弃了东西。 运行 这段代码检查并生成 shell 并继承 PS1
(如果可用):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
pid_t pid;
char const *ps1 = getenv("PS1");
if(ps1 != NULL) {
puts(ps1);
} else {
puts("PS1 is NULL");
}
pid = fork();
if(pid == -1) {
fputs("fork broke. Aborting.\n", stderr);
return -1;
} else if(pid == 0) {
execl("/bin/sh", "sh", NULL);
} else {
wait(NULL);
}
puts("Continuing here after the shell exited.");
return 0;
}
对我来说,如果 PS1
未导出,这将打印 PS1 is NULL
并打开默认 PS1
的 shell,如果我 运行,则保留提示] 在 export PS1
.
之后再次出现
export
区分了 shell 变量和环境变量。如果您希望子进程继承一个 shell 变量,请通过 export
将其设置为环境变量。
我想创建远程 bash(通过 tcp 套接字),我写了这段代码:
// servfd is descriptor to server socket
int sockfd = accept(servfd,&addr,sizeof(addr));
dup2(sockfd,fileno(stdin));
dup2(sockfd,fileno(stdout));
dup2(sockfd,fileno(stderr));
setenv("PS1","# ",1);
execl("/system/bin/sh","sh",NULL);
并且提示没有打印到套接字,但是当我发送命令等时:'echo test'它正在工作但没有提示打印。
我找到了必须使用的解决方案 /dev/ptmx
再次编辑:我是愚蠢的。问题是 shell 不是交互式的,因为 std(in|out|err)
不再是 ttys。使用
execl("/system/bin/sh", "sh", "-i", "NULL");
// along with the fork dance from below if you want to continue with the main
// program after this
强制 mksh
进行交互,在这种情况下,它应该每次都向 stderr
打印提示。这也将使 mksh
解释 ~/.mkshrc
,其中可能设置了 PS1
。如果未在此处设置,您仍然需要导出 PS1
,并且 system()
的问题仍然存在。如果设置在那里,
system("sh -i");
旧的,可能已过时的答案部分:
编辑:这里的工作比我最初怀疑的要多一些。 system()
在到达其子 shell 的过程中丢弃环境变量。这与它 运行s(在这种情况下)
execl("/bin/sh", "sh", "-c", "sh", NULL);
(也就是说,运行宁sh -c sh
export
ed PS1
也可以重现)。我不太清楚为什么 sh -c sh
丢弃 PS1
;它不会对其他环境变量执行此操作。
在这种情况下,可以通过使用 fork
和 exec
来模仿 system()
调用而不会产生这种效果,如下面的代码所示。但是,PS1
仍需要 export
编辑才能让子进程看到它。
所以,最有可能的原因是 PS1
没有 export
ed 并且 system()
丢弃了东西。 运行 这段代码检查并生成 shell 并继承 PS1
(如果可用):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
pid_t pid;
char const *ps1 = getenv("PS1");
if(ps1 != NULL) {
puts(ps1);
} else {
puts("PS1 is NULL");
}
pid = fork();
if(pid == -1) {
fputs("fork broke. Aborting.\n", stderr);
return -1;
} else if(pid == 0) {
execl("/bin/sh", "sh", NULL);
} else {
wait(NULL);
}
puts("Continuing here after the shell exited.");
return 0;
}
对我来说,如果 PS1
未导出,这将打印 PS1 is NULL
并打开默认 PS1
的 shell,如果我 运行,则保留提示] 在 export PS1
.
export
区分了 shell 变量和环境变量。如果您希望子进程继承一个 shell 变量,请通过 export
将其设置为环境变量。