文章目录
- 命令行中输入参数长度过长
- 匿名管道从父进程到子进程传参
- `[]*os.File{}`
- `os.NewFile`和`io.ReadAll`
- exe.LookPath
- syscall.Exec
- [`strings.Split(msgStr, " ")`](#
strings.Split(msgStr, " ")
) - [/bin/ls: cannot access '': No such file or directory](#/bin/ls: cannot access '': No such file or directory)
- 代码
命令行中输入参数长度过长
用户输入参数过长或包含特殊字符时,该方案可能遇到的问题包括:
-
参数长度限制:大多数命令行环境对单个命令行参数的长度都有一定限制,超出这个限制后,参数可能无法完整传递给程序。解决方法是在程序中处理长参数时采用多参数模式或通过文件传递参数。
-
特殊字符转义问题:特殊字符如引号、空格、换行符等,在命令行中通常需要正确转义才能作为参数的一部分。例如,如果参数中包含空格,则应该将整个参数用双引号括起来(在POSIX兼容的shell中),如
"this is a long param with spaces"
。在处理这类参数时,你的程序需要能够识别并正确解析这些转义规则。 -
内部处理逻辑问题:如果
Contain_init
函数内部没有做好对长参数或特殊字符的处理,那么即便参数能成功传入函数,也可能导致函数执行失败或不按预期工作。
匿名管道从父进程到子进程传参
- 管道就是两个进程传输的一个中间缓存区
- 管道一般固定大小4KB
- 半双工(即一次只能在一个方向上传输数据)
- 管道有空余地方才能写
- 管道有被写的部分才能读
[]*os.File{}
在Go语言中,[]*os.File{}
是一个指向 os.File
类型的指针切片(slice)的初始化表达式。os.File
是Go标准库 os
包中的一个结构体类型,它代表一个打开的文件对象,可以是常规的磁盘文件,也可以是管道、终端设备等其他类型的I/O资源。
[]*os.File{}
表示一个存放 *os.File
类型指针的切片,其中的星号 *
表示指针,表示切片中的元素是指向 os.File
结构体的指针。
例如,[]*os.File{readPipe}
表示一个只包含一个元素的 os.File
指针切片,其中 readPipe
是一个已打开的 os.File
类型的指针。
在Go的 os/exec
包中,当我们创建一个 exec.Cmd
结构体实例来执行外部命令时,可以通过 Cmd.ExtraFiles
字段传递这样一个包含文件指针的切片。这样做的目的是在执行外部命令时,将这些文件描述符传递给子进程,以便子进程能够访问和操作这些文件资源,比如进行进程间通信(IPC)等。
os.NewFile
和io.ReadAll
在这段Go语言代码中,os.NewFile
和 io.ReadAll
分别用于从底层文件描述符创建 os.File
对象和读取该文件的所有内容。
pipe := os.NewFile(uintptr(fdIndex), "pipe")
:fdIndex
是一个整数,表示一个已知的文件描述符索引。(因为3已经是传过来的文件描述符 因为每个进程默认都会有3个文件描述符,分别是标准输入、标准输出、标准错误。这3个是子进程一创建的时候就会默认带着的)os.NewFile
函数接收两个参数:一个是文件描述符的数值表示(在这里转换为uintptr
类型),另一个是给这个文件描述符起的名称(这里是字符串 "pipe")。
os.NewFile 函数接收两个参数,第一个参数是一个 uintptr 类型的值,表示一个已存在的文件描述符;第二个参数是一个字符串,用于指定文件的名称(在这个上下文中,通常是一个描述性的名称,而非实际路径)。
msg, err := io.ReadAll(pipe)
:io.ReadAll
是一个从给定的io.Reader
接口(在这里是pipe
,它实现了io.Reader
接口)读取所有数据直到EOF(End Of File)为止的函数。- 它返回两个值:一个是读取到的数据(在这里是
msg
变量),类型是[]byte
(字节数组);另一个是错误信息(err
),如果读取过程中发生错误,err
将非空。 - 这行代码尝试从刚才创建的
pipe
文件对象中读取所有的数据,并将读取到的内容存储在msg
变量中。
exe.LookPath
在Go语言的 os/exec
包中,exec.LookPath
函数是一个用来查找给定可执行文件路径的函数。其原型如下:
go
func LookPath(name string) (string, error)
当你调用 exec.LookPath(cmdArray[0])
时,cmdArray
一个字符串数组,其中 cmdArray[0]
是你想执行的命令或程序的名字(不包含其完整路径)。LookPath
函数会根据当前系统的环境变量 $PATH
来搜索这个名字对应的可执行文件的完整路径。
如果找到了对应可执行文件的路径,LookPath
函数会返回该路径;如果没有找到,则返回一个空字符串和一个错误对象。这个功能常用于在执行外部命令之前验证命令是否存在,这是执行 exec.Command
之前的一个常见前置步骤。
例如,假设你有一个 cmdArray := []string{"ls", "-l", "."}
,你想执行 ls -l .
命令。在执行命令前,你可能会先调用 exec.LookPath(cmdArray[0])
来查找系统上是否存在名为 ls
的可执行文件。如果存在,接下来才会安全地创建和执行 exec.Command(cmdArray[0], cmdArray[1:]...)
。
syscall.Exec
https://xieys.club/go-syscall-exec/
https://gobyexample-cn.github.io/execing-processes
strings.Split(msgStr, " ")
strings.Split(msgStr, " ")
是 Go 语言中的一个字符串处理函数,来自 "strings" 包。这个函数接收两个参数:
msgStr
:这是一个字符串变量,你想在此字符串上执行分割操作。" "
:这是分割符,一个空格字符,表示你希望通过空格来拆分msgStr
。
函数执行后,它会返回一个字符串切片([]string
类型),其中的元素是 msgStr
按照空格分隔后的各个子串。例如,如果 msgStr
是 "hello world how are you"
,那么执行 strings.Split(msgStr, " ")
之后的结果将会是 ["hello", "world", "how", "are", "you"]
。
这种操作常用于将一串以空格分隔的单词转换为单词列表,便于后续遍历、处理或分析。
/bin/ls: cannot access '': No such file or directory
由于
c
err:=syscall.Exec("/bin/ls",argv,os.Environ())
argv为["/bin/ls",""]
就会出现这样的问题,解决办法就是把""
对应的这个从切片中去掉。也不知道为啥会这样,可能是Split的机制导致
如果有尾部的空格字符,分割结果中自会包含因尾部空格产生的空字符串元素。