使用 execv() 时没有这样的文件或目录
no such file or directory when using execv()
我正在尝试编写一个基本的 shell 来解释简单的命令,例如 date、ls 等 c 语言
我首先像这样获取 PATH 变量,然后将其传递给 execv() 函数。
const char *name = "PATH";
char *value;
value = getenv(name)
然后我打印出这个值,我得到了这个:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
请注意,我正在使用 virutalbox 运行 Ubuntu。这是我用来尝试一个简单的 ls 命令的代码。在下面的代码中,变量行是用户编写的实际命令,在我们的例子中是 "ls"
pid_t pid, wpid;
int status;
pid = fork();
if (pid == 0) {
// Child process
if (execv(value, line) == -1) {
perror("lsh");
}
exit(EXIT_FAILURE);
}
else if (pid < 0) {
// Error forking
perror("lsh");
}
else {
// Parent process
do {
wpid = waitpid(pid, &status, WUNTRACED);
}
while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
我得到的结果是这样的:
lsh: no such file or directory
有什么想法吗?
execv()
系统调用使用您在第一个参数中指定的名称作为可执行文件的文件名;它不进行基于路径的搜索。
也就是说,如果你指定"lsh"
作为第一个参数,则当前目录下必须有一个可执行文件lsh
。
如果您想要基于路径的搜索,请将 execv()
替换为 execvp()
。否则,在第一个参数中指定命令的路径名——绝对或相对,但绝对更正常。
请注意,如果任何 exec*()
函数 return 都失败了。无需测试 return 值;它永远是-1。
value
和 line
的内容需要遵循:
char *value = "ls";
char *line[] = { "ls", "-l", 0 };
execvp(value, line);
或者,更传统地说:
execvp(line[0], line);
如果您自己分析 PATH,则需要 line[0]
指向您从 PATH 创建的完整文件名,然后使用 execv()
而不是 execvp()
.
execv
的第一个参数是 运行 的命令。这意味着您正在尝试 运行 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
作为命令。
假设 line
数组中的第一个值是您要调用的程序,您应该改为这样做:
execv(line[0], line);
如果要执行基于路径的搜索,请改用execvp
(无需手动提取 PATH 变量):
execvp(line[0], line);
编辑:
例如,假设您想要 运行 ls -l /usr/bin /var/log
,您的数组将如下所示:
char *line[] = { "ls", "-l", "/usr/bin", "/var/log", NULL};
我正在尝试编写一个基本的 shell 来解释简单的命令,例如 date、ls 等 c 语言
我首先像这样获取 PATH 变量,然后将其传递给 execv() 函数。
const char *name = "PATH";
char *value;
value = getenv(name)
然后我打印出这个值,我得到了这个:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
请注意,我正在使用 virutalbox 运行 Ubuntu。这是我用来尝试一个简单的 ls 命令的代码。在下面的代码中,变量行是用户编写的实际命令,在我们的例子中是 "ls"
pid_t pid, wpid;
int status;
pid = fork();
if (pid == 0) {
// Child process
if (execv(value, line) == -1) {
perror("lsh");
}
exit(EXIT_FAILURE);
}
else if (pid < 0) {
// Error forking
perror("lsh");
}
else {
// Parent process
do {
wpid = waitpid(pid, &status, WUNTRACED);
}
while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
我得到的结果是这样的:
lsh: no such file or directory
有什么想法吗?
execv()
系统调用使用您在第一个参数中指定的名称作为可执行文件的文件名;它不进行基于路径的搜索。
也就是说,如果你指定"lsh"
作为第一个参数,则当前目录下必须有一个可执行文件lsh
。
如果您想要基于路径的搜索,请将 execv()
替换为 execvp()
。否则,在第一个参数中指定命令的路径名——绝对或相对,但绝对更正常。
请注意,如果任何 exec*()
函数 return 都失败了。无需测试 return 值;它永远是-1。
value
和 line
的内容需要遵循:
char *value = "ls";
char *line[] = { "ls", "-l", 0 };
execvp(value, line);
或者,更传统地说:
execvp(line[0], line);
如果您自己分析 PATH,则需要 line[0]
指向您从 PATH 创建的完整文件名,然后使用 execv()
而不是 execvp()
.
execv
的第一个参数是 运行 的命令。这意味着您正在尝试 运行 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
作为命令。
假设 line
数组中的第一个值是您要调用的程序,您应该改为这样做:
execv(line[0], line);
如果要执行基于路径的搜索,请改用execvp
(无需手动提取 PATH 变量):
execvp(line[0], line);
编辑:
例如,假设您想要 运行 ls -l /usr/bin /var/log
,您的数组将如下所示:
char *line[] = { "ls", "-l", "/usr/bin", "/var/log", NULL};