os.Args[0] for program executed by go

1,257 views
Skip to first unread message

Santhosh Ram Manohar

unread,
Jun 1, 2017, 1:41:45 PM6/1/17
to golang-nuts
When I run a go program from the shell, os.Args[0] is the program name. If I invoke the same program using go's exec then os.Args[0] is not the program name, rather its the first argument that I pass.

Here is a simple program to show this behavior, installed as gocmd in my $GOPATH/bin

func main() {
        fmt.Println(os.Args)
        if os.Args[0] == "self" {
                return
        }
        cmd := &exec.Cmd{
                Path:   <path to the program in $GOPATH/bin>,
                Args:   []string{"self", "selftest"},
                Stdout: os.Stdout,
                Stderr: os.Stderr,
        }
        if err := cmd.Run(); err != nil {
                fmt.Println("Run failed..", err)
        }
}

$ gocmd test1 test2
[gocmd test1 test2]
[self selftest]
$

Isn't the args[0] being the program name a behavior of exec call in Linux ? What is the reason for this difference only for the binaries executed by the exec package ?

thanks,
Santhosh.

Jan Mercl

unread,
Jun 1, 2017, 1:45:56 PM6/1/17
to Santhosh Ram Manohar, golang-nuts
On Thu, Jun 1, 2017 at 7:41 PM Santhosh Ram Manohar <santho...@gmail.com> wrote:

> Args: []string{"self", "selftest"},

Here you explicitly pass arsg[0] == "self" and that's what the program gets.

> What is the reason for this difference only for the binaries executed by the exec package ?

--

-j

Santhosh Ram Manohar

unread,
Jun 1, 2017, 2:03:10 PM6/1/17
to golang-nuts, santho...@gmail.com


On Thursday, June 1, 2017 at 10:45:56 AM UTC-7, Jan Mercl wrote:
On Thu, Jun 1, 2017 at 7:41 PM Santhosh Ram Manohar <santho...@gmail.com> wrote:

> Args: []string{"self", "selftest"},

Here you explicitly pass arsg[0] == "self" and that's what the program gets.

Yes, because I already have the program name in "Path". When Run() calls exec syscall i would expect Args[0] to be program name because from the exec point of view its no different from how shell would invoke it, no ?

Marvin Renich

unread,
Jun 1, 2017, 3:21:49 PM6/1/17
to golang-nuts
* Santhosh Ram Manohar <santho...@gmail.com> [170601 14:03]:
>
>
> On Thursday, June 1, 2017 at 10:45:56 AM UTC-7, Jan Mercl wrote:
> >
> > On Thu, Jun 1, 2017 at 7:41 PM Santhosh Ram Manohar <santho...@gmail.com
> > <javascript:>> wrote:
> >
> > > Args: []string{"self", "selftest"},
> >
> > Here you explicitly pass arsg[0] == "self" and that's what the program
> > gets.
> >
>
> Yes, because I already have the program name in "Path". When Run() calls
> exec syscall i would expect Args[0] to be program name because from the
> exec point of view its no different from how shell would invoke it, no ?

The documentation for Args says:

// Args holds command line arguments, including the command as Args[0].
// If the Args field is empty or nil, Run uses {Path}.
//
// In typical use, both Path and Args are set by calling Command.

If you use Command, and then print the Args field, you see the proper
setup for Args. Try https://play.golang.org/p/phIbvlwa8s

Run is using Path as the command to execute and Args as the argv
argument to the underlying execve call (or corresponding Windows API).
The documentation for execve explicitly says that by _convention_ the
first string in argv (argv[0]) should contain the filename associated
with the file being executed. However, this is just convention, and the
caller of execve is not required to do so. Not setting argv[0] (i.e.
Args[0]) to the name of the command will normally get undesired results,
since all well-written programs expect argv[0] to be the command name,
not the first command argument.

...Marvin

Reply all
Reply to author
Forward
0 new messages