Skip to content

Working Dir in Std Os Package

Go standard library provides os pacakge to trackle with os related concepts, for example, the working dir. Working dir is a os level concept rather than a concept maintained by os package. Indeed, os package doesn't reinvent the wheel but rely on the operation system to tackle it.

Working dir is a concept for a process rather than an executable. So statement "the working dir of binary ./bin/server is ~/workspace/server" is totally wrong.

Linux /proc directory, a Process-Specific subdirectory, contains one subdirectory for each process running on the system named by process id PID. It implies once a process dies, it won't be shown under /proc. Zombie processes will still exist as kernel's process table still maintains information(such as PID) for the zombie process, even though most of its resources such as memory, file descriptors are released.

A process can read its own /proc/<PID> with no extra permissions, but not for the other processes.

There are many items under /proc/<PID>, here we list a part of them, you can see the whole table here.

  • cmdline: Command line arguments
  • cwd: Link to the current working directory
  • exe: Link to the executable of this process
  • root: Link to the root directory of this process
  • stat ...

The cmdline is a file which stores how the process is started, and cwd, exe and root are symbol links to another place. The stat contains more useful information but it's slighty out of scope of current topic.

As linux maintains these information, it means the system call is the source of truth to get the cwd and root.

The initial value of root is /. The initial value of cwd is determined by the place you start your binary. For example: $(/a/b/c) means currently the shell is under path /a/b/c.

$(/a/b/c) ./bin/server -> /a/b/c
$(/a/b) ./bin/server -> /a/b

Call chdir changes the current working directory of the calling process to the directory specified in path. Because the working dir is determined by the place that the process starts. Os package has corresponding function os.Chdir.

Call chroot changes the root directory of the calling process to that specified in path. This directory will be used for pathnames beginning with /. The root directory is inherited by all children of the calling process. Os package doesn't have API for chroot yet.

Relative Path and Working Dir

Absolute path is starightforward, but relative path must have a base path otherwise 'relative' doesn't make sense. The relative path is related to current working dir.

Go os package allows several operations based on file with relative path, however, os package doesn't resolve the relative path to absolute path, but relies on the operation system.

For example, os.ReadFile uses syscall.Open and syscall.Stat underlying without any file path resolving.

Working Dir Issue in Our Scenario

I have mimssed a lot of blogs so this may a bit confusion due to lack backgrounds. In short, with the help of the cli tool, we have achieved to combine multiple services together into a single binary. Even though they're putting together into a single binary and run in a single process, well isolations are designated so go module versions are retained and used packages are different underlying. Besides, platform integration ensures the deployment platform could manage the logical separated services well.

I haven't realized the working dir issue until we try to deploy a pair. The dependency service reads some files under its own repo with relative path. However, as they're combined together now the working dir changes and caused a file not found error.

Services combined together are still logically separated so it means each service should have its own working dir, as currently we don't put all services source code under the same place. In this case, process level working dir doesn't solve our goal so we need more actions to maintain the working dir inside the toolchain side.

TODO: write our solution.