how to get the full path of current process' executable file

4,932 views
Skip to first unread message

Shark Flh

unread,
Mar 13, 2014, 1:45:20 AM3/13/14
to golan...@googlegroups.com
how to get the full path of current process' executable file

John

unread,
Mar 13, 2014, 1:46:57 AM3/13/14
to Shark Flh, golan...@googlegroups.com
path, err := os.Getwd()

path is a string.


On Mar 12, 2014, at 10:45 PM, Shark Flh <flhs...@gmail.com> wrote:

how to get the full path of current process' executable file

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jesse McNelis

unread,
Mar 13, 2014, 1:55:18 AM3/13/14
to John, Shark Flh, golang-nuts
On Thu, Mar 13, 2014 at 4:46 PM, John <jo...@jclo.co> wrote:
path, err := os.Getwd()

path is a string.


That will give you the directory where the process was started not the executable file that the process is running.
I don't believe there is a cross platform way to get the executable file for a process.

On Linux, /proc/<pid>/exe will be a symlink to the executable file.
I've no idea about Windows.

brainman

unread,
Mar 13, 2014, 2:08:34 AM3/13/14
to golan...@googlegroups.com, John, Shark Flh, jes...@jessta.id.au
On Thursday, 13 March 2014 16:55:18 UTC+11, Jesse McNelis wrote:

> ... I've no idea about Windows.


Alex

Shark Flh

unread,
Mar 13, 2014, 2:24:07 AM3/13/14
to golan...@googlegroups.com
looks we have a method can get it in windows.  
any one can provide a sample code for linux ?

John

unread,
Mar 13, 2014, 2:32:42 AM3/13/14
to Shark Flh, golan...@googlegroups.com
my example should work for Linux

Alex Skinner

unread,
Mar 13, 2014, 2:46:45 AM3/13/14
to golan...@googlegroups.com
os.Readlink("/proc/self/exe") 

Gyepi SAM

unread,
Mar 13, 2014, 2:48:40 AM3/13/14
to golang-nuts
On Thu, Mar 13, 2014 at 04:55:18PM +1100, Jesse McNelis wrote:
> On Linux, /proc/<pid>/exe will be a symlink to the executable file.

My redux program has some generic code that should be cross platform [1].

https://github.com/gyepisam/redux/blob/master/redux/install.go#L90

[1] That is to say, it works on unix and the 1+ Windows users have not
complained that it doesn't work.

-Gyepi

Dobrosław Żybort

unread,
Mar 13, 2014, 3:54:29 AM3/13/14
to golan...@googlegroups.com
Too bad you did not search on stackoverflow:
http://stackoverflow.com/a/15038241/1722542

My answer there:

Use package bitbucket.org/kardianos/osext.

It's providing function Executable() that returns an absolute path to the current program executable. It's portable between systems.

Online documentation

package main

import (
    "bitbucket.org/kardianos/osext"
    "fmt"
)

func main() {
    filename, _ := osext.Executable()
    fmt.Println(filename)
}

Best regards,
Dobrosław Żybort

Shark Flh

unread,
Mar 13, 2014, 5:16:31 AM3/13/14
to golan...@googlegroups.com
Thanks!

John

unread,
Mar 13, 2014, 2:18:10 AM3/13/14
to Jesse McNelis, Shark Flh, golang-nuts
Here’s something I whipped up to make up for my previous message


I think this might work on Windows with PathVar set to “Path” but I can’t test it.

It also doesn’t work in the playground :)

Gyepi SAM

unread,
Mar 13, 2014, 10:24:27 AM3/13/14
to golang-nuts
On Wed, Mar 12, 2014 at 11:18:10PM -0700, John wrote:
> Here's something I whipped up to make up for my previous message
>
> http://play.golang.org/p/lZ0WFx90qF
>
> I think this might work on Windows with PathVar set to "Path" but I can't test it.
>
> It also doesn't work in the playground :)

Won't work reliably off the playground either ;)


1 case '.', os.PathSeparator:
2 wd, err := os.Getwd()
3 return path.Join(wd, cmdName), err
4 }
5 directories := strings.Split(os.Getenv(PathVar),
6 string(os.PathListSeparator))
7 for _, directory := range directories {
8 fi, err := os.Stat(path.Join(directory, cmdName))
9 if err == nil && fi.Mode().IsRegular() {
10 return path.Join(directory, cmdName), nil
11 }
12 }

Line 3 works if the path begins with a dot but produces an incorrect
result when the path begins with a separator.

What you want there is to add wd if the path begins with a dot or does
NOT begin with a path separator (since it is then a relative path).
However, that may produce correct but unnecessarily verbose paths
so you have to call path.Clean on the result before returning it.

Also lines 5 to 12 basically duplicate os/exec.LookPath() but without handling edge cases,
errors or testing for executable status.

-Gyepi

Rob Pike

unread,
Mar 13, 2014, 4:37:29 PM3/13/14
to golang-nuts
Let me just inject the observation that almost every time I've seen a
request for this functionality, it's been to do something that
shouldn't be done anyway. Other than debuggers getting access to
symbol tables, a facility that the operating system should provide,
there should be no reason for a program to care where the executable
resides in the file system. A program that does care is less capable
than a program that does not.

-rob

Sander van Harmelen

unread,
Mar 13, 2014, 5:11:53 PM3/13/14
to Rob Pike, golang-nuts
Even though I generally would agree with your observation, I do think there are valid use cases you can think of. For example when you want your executable to check for a config file at some default locations when it is being started without any options (and then one of those default locations being the application directory of course :)

Or when you want to cache some stuff (over restarts and time, so using /tmp wouldn't be sufficient) in a .gob file, it would also be nice if the executable could just place that .cache file besides the executable itself. This latter example could of course also be in a config file, but then you at least should be able to look for the config file (see my first example ;)

Or do you still consider this bad practice and so you would make it mandatory to specify the config file when calling the executable?

S.

Aram Hăvărneanu

unread,
Mar 13, 2014, 5:16:03 PM3/13/14
to Sander van Harmelen, Rob Pike, golang-nuts
Put the config file in a known place.

--
Aram Hăvărneanu

Shawn Milochik

unread,
Mar 13, 2014, 5:16:30 PM3/13/14
to golan...@googlegroups.com
On Thu, Mar 13, 2014 at 5:11 PM, Sander van Harmelen <SvanHa...@schubergphilis.com> wrote:
Even though I generally would agree with your observation, I do think there are valid use cases you can think of. For example when you want your executable to check for a config file at some default locations when it is being started without any options (and then one of those default locations being the application directory of course :)

Or when you want to cache some stuff (over restarts and time, so using /tmp wouldn't be sufficient) in a .gob file, it would also be nice if the executable could just place that .cache file besides the executable itself. This latter example could of course also be in a config file, but then you at least should be able to look for the config file (see my first example ;)

Or do you still consider this bad practice and so you would make it mandatory to specify the config file when calling the executable?


It seems the convention for things like this are dotfiles in .config in the user's home folder, which is more flexible because it allows separate settings per user. Also, the user running the program frequently won't have write access to the /bin folder, or wherever the program lives.


Alex Skinner

unread,
Mar 13, 2014, 5:17:08 PM3/13/14
to golan...@googlegroups.com
The only reason I've used this functionality is for assuming that a conf file is in the same directory as the binary.  Without pulling binary location, you must insist on a set location, require the user to cd to the directory first, or provide a config location argument...none of which seem user friendly.   Assuming binary 'myTool' and conf file 'myTool.conf' that come packaged together in a tarball, what is your general recommendation?

Thanks,
Alex

Caleb Spare

unread,
Mar 13, 2014, 5:17:13 PM3/13/14
to Sander van Harmelen, Rob Pike, golang-nuts
These are all bad practices. When I run a program I want it to do the
same thing regardless of where the executable happens to live.

Alan Shreve

unread,
Mar 13, 2014, 5:20:06 PM3/13/14
to Dobrosław Żybort, golan...@googlegroups.com
This is the best answer. One time I wrote my own version of this, and it was not as portable as I’d have liked. Use osext. It’s cross-platform *even when cross compiling* because it does not rely on cgo which is pretty huge.

Daniel Theophanes

unread,
Mar 13, 2014, 5:47:59 PM3/13/14
to golan...@googlegroups.com

When I deploy a program to a Windows machine, it may be on the S: drive,
may be on the D: drive, and I don't know where it should read a configuration
file when I compile it. So in fact, being able to get the executable's location
can make it more capable. I could pass it the configuration on the command line
but that is awkward for windows "services". So while I know it isn't best practice in many
environments, there is a place for it, even if you haven't encountered it yourself.

-Daniel

Shawn Milochik

unread,
Mar 13, 2014, 5:59:41 PM3/13/14
to golan...@googlegroups.com
On Thu, Mar 13, 2014 at 5:47 PM, Daniel Theophanes <kard...@gmail.com> wrote:

When I deploy a program to a Windows machine, it may be on the S: drive,
may be on the D: drive, and I don't know where it should read a configuration
file when I compile it. So in fact, being able to get the executable's location
can make it more capable. I could pass it the configuration on the command line
but that is awkward for windows "services". So while I know it isn't best practice in many
environments, there is a place for it, even if you haven't encountered it yourself.


I think the points made previously about the application behavior remaining predictable no matter where the binary is, the per-user config capability, and write permission issues preclude this method entirely.

Even Windows has the concept of a user's home folder and hidden files.

Nathaniel Nutter

unread,
Mar 13, 2014, 6:47:08 PM3/13/14
to golan...@googlegroups.com
On Linux one "standard" for where to store such things is addressed here:
http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html

I'm not aware of a similar standard on Windows but there are similar environment variables:
http://ss64.com/nt/syntax-variables.html

Dobrosław Żybort

unread,
Mar 14, 2014, 5:34:03 AM3/14/14
to golan...@googlegroups.com, Sh...@milochik.com
The more I use different programs the more I like portability.

Download, unzip, run.
Do I want to use my program on different computer?
Zip folder with program, move to other computer, unzip and run with all my prefferences.

This way I don't need to search for my preferences in user home folder (and almost all programs I use on Windows are portable, mostly thanks to http://portableapps.com/).

When I run my web scrapers and bots on VPS from cron I also use config files in folder with program executable.
When I want move my program to other server then I just move folder, add cron job and it working again as if nothing has changed.

RickyS

unread,
Mar 14, 2014, 6:46:04 AM3/14/14
to golan...@googlegroups.com, Sh...@milochik.com
System fixing software often runs from a USB stick or optical drive.  Configuration data may be needed, and its on the media.  Sometimes an installer can't be run because the system being fixed is too seriously broken.  So I think there are valid uses for such a facility.  But not often.  Żybort has a point.

Eric Chai

unread,
Jan 8, 2020, 12:37:57 AM1/8/20
to golang-nuts

Tamás Gulácsi

unread,
Jan 8, 2020, 3:39:11 AM1/8/20
to golang-nuts
Dear Thread Necromancer,

You're right that kardianos/osext has been moved to github, but

  1. that reply is from 2014
  2. os.Executable returns the required information since 1.8 (2017-02).
  3. kardianos/osext uses os.Executable since 2017-03.
  4. It's documented in the README of kardianos/osext that it's obsolete since Go 1.8.
Reply all
Reply to author
Forward
0 new messages