Is it possible with "-s deploy" to include libraries loaded at runtime

Hi @probono. I downloaded yesterday golang go1.15.2

Even after the simplest tutorials I can read your go code much easier, and I’ve already found features that I REALLY like (e.g., multiple function returns and others).

So this process really interests me. I will be downloading the source code and making a personal version of appimagetool to do some tests here, give me a bit of time to get up to speed, and I will report back here.

1 Like

That’s great news @Juuliuus. For me it was a lot of fun beginning to start using Go. I was watching some of the longer tutorials on YouTube, and then just wanted a project to apply what I had seen. This project is the result :slight_smile:

Hi @probono

I have a question regarding the expansion of an AppImage into /tmp folder.

For instance my appimage is expanded to:

I thought I had seen how that path is determined but I can’t find it anywhere. Could you tell me how that path is determined? I do know that after my app has started the $APPDIR var is the path from above. How / Who sets the $APPDIR env. var? I do see that your AppRun script finds HERE from readlink, so somehow APPDIR is being set before AppRun is executed??

In my testing I want to provide an APPDIR env. var. If I’m understanding the .env file requirements then I need to provide an APPDIR that WILL BE the expanded tmp location, so I want to try making that name determined absolutely using the guid I generate…

Hi @probono & @azubieta I’ve used the appimagecrafers files with mixed, and interesting, success…

I’ve included links to the appimages, the go code, and straces & stderrs below.

To summarize what has gone before and where we are now:

I will refer to these #'s (and all the files also use them):
0 : standard appimage deploy, just using “deploy” flag.
1 : first self-contained (-s deploy) appimage
2 : Same as 1, this time including libsqlite lib (runtime loaded)
3 : using azubieta’s .env, AppRun, and hook lib (-s -l deploy)

My test beds are (all from April 2020) kubuntu 20.04 (dev machine), and VM’s of OpenSuse Leap 15.2, nixos, Ubuntu 20.04, manjaro, and fedora.v32.

0 : worked in all beds except OpenSuse, and this was due to its using glibc 2.26, while my program was built against glibc 2.31. (note: in nixos appimages are run with appimage-run program from the nix-store: “appimage-run /path/appimage”)

1 (and 2) : now worked in OpenSuse, but stopped working in nixos. Nixos gives permission denied messages re: ld linux file (once this is worked out I intend to file an issue with nixos). At this time probono also tested 1 in Ubuntu 18 and 16, both worked.

3 : Now it is similar to 0, everything works except, this time, both OpenSuse and nixos fail with core dumps. This makes me suspect the wrong glibc is being used, but I’m not sure. So I doubt very much that 3 will run on 18’s or 16’s. One interesting thing is that the stderrs of the working systems is much cleaner. There is a problem (at least for my program) in this version too: the process table lists two “commandoo”'s, one normal and one commandoo.AppImage. This messes with my program because it inspects the process list to determine if another commandoo is already running (more on this and how it may affect you below).

The process I used:

I added a func in appdirtool.go to gather all the paths that were previously being set by probono’s AppRun script (this is in the go snippet file). On “-s -l deploy” these were written to the .env file. azubieta’s AppRun and were then copied to the AppDir, and then appimage tool was run to generate the AppImage. I did not package the appimagetool executable into an AppImage, I just used the freshly compiled local copy of it, pulling the needed executables (patchelf, etc.) from probonos appimagetool 556 buld…

The appimagecrafters AppRun and hooks lib are “fresh”, they were downloaded a couple days ago.

TIP 1: It will not be (immediately) possible to run 3 because of the process list problem I mentioned above. By default commandoo will not run if another copy is open. To solve this open 1 or 2 first. Then go to Options (lower right), and check off “allow multiple copies”. They all use the same settings file and so after this, 3 can be run (it will complain, but you can just say yes).

TIP 2: commandoo is a CLI program, so it is easy to get the running environment. After you first start up a default db is installed (.config/commandoo). While the command list is focused press ctrl-shift f, type printenv, enter. Then type alt-r to run the command line.

Please keep in mind that these copies of commandoo are intermediate versions and not released versions, so don’t give them out to anyone, and just delete them when you’ve gotten out of them all that you need. I will be deleting them when everyone has gotten what they want. The current release version, if you want it, can be downloaded from

No, it does not “expand”, it gets mounted there.

The path changes every time the AppImage is run. It is random.

The APPDIR variable will be set by the AppImage runtime if your AppDir is inside an AppImage. But if the user extracts the AppImage, then it will not be set by the AppImage runtime.

Hence, better contstruct it yourself like this:

APPDIR="$(dirname "$(readlink -f "${0}")")"

The AppRun sets APPDIR if it’s missing to the dire where it’s located.

Hello folks!
Let’s describe the appimage-builder workflow:

Please feel free to open issues in the appimage-builder repo if you need to clarify something else. We can also arrange a chat meeting.

Yes I had seen that. While I was embedding myself in the go code I had thought that I may also need control of the /tmp path using the UUID. But on the first test I had seen that $APPDIR was available and so the question became moot.

And the code snippet: well that answers why I couldn’t find APPDIR’s set command. Now I just need to figure out appimagekit gets that code into the appimage. Using appimagetool I didn’t notice any runtime being installed, I’ll look again.

BTW, probono, I forgot to mention I had also changed the appdirtool’s libc path, prepending “/opt”

Hi, thanks for the reply. Yes, I want to delve into this deeper and I will look at those links and check what I’ve done so far. Just wanted everyone to know that it does work, just not as expected, and that people could duplicate what I’ve found if they wanted.

As a note I’m new to the world of ELF, having never needed to go there before. But I’m really enjoying it. So if anybody wants to share some good tools to use while debugging this issue they would be gratefully accepted. For instance, I had no idea how useful strace is! Any other commands that one shouldn’t live without??

At this point I need some guidance about what I can do. The strace on OpenSuse fails on opening / loading:


openat(AT_FDCWD, “/tmp/.mount_commanh9gLMG/lib/x86_64-linux-gnu/”, O_RDONLY|O_CLOEXEC) = 4
read(4, “\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@N\0\0\0\0\0\0”…, 832) = 832
lseek(4, 98304, SEEK_SET) = 98304
read(4, “\1\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”…, 672) = 672
fstat(4, {st_mode=S_IFREG|0664, st_size=102600, …}) = 0
lseek(4, 98304, SEEK_SET) = 98304
read(4, “\1\0\0\0\4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0”…, 672) = 672
mmap(NULL, 110792, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 4, 0) = 0x7fb7db70f000
mprotect(0x7fb7db713000, 90112, PROT_NONE) = 0
mmap(0x7fb7db713000, 61440, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0x4000) = 0x7fb7db713000
mmap(0x7fb7db722000, 12288, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0x13000) = 0x7fb7db722000
mmap(0x7fb7db726000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0x16000) = 0x7fb7db726000
mmap(0x7fb7db728000, 368, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fb7db728000
mmap(0x7fb7db729000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0x18000) = 0x7fb7db729000
close(4) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb7db70d000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb7db70b000
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb7db708000
arch_prctl(ARCH_SET_FS, 0x7fb7db708780) = 0
mprotect(0x7fb7df7b3000, 12288, PROT_READ) = 0
— SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_ACCERR, si_addr=0x7fb7dff00b60} —
+++ killed by SIGSEGV (core dumped) +++

I found a couple of paths in .env that were not correct and fixed them by hand. I also tried moving the libbsd to the “libc” path thinking it could be mis-filed. In all cases the resulting appimage works on my dev machine, but gives the same failure(s) on OpenSuse.

The last self-contained, appimage (probono’s method) that runs on OpenSuse gives these strace entries for libbsd:

openat(AT_FDCWD, “/tmp/.mount_commanVGEEVu/usr/bin/…/…/lib/x86_64-linux-gnu/././…/…/usr/bin/”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, “/tmp/.mount_commanVGEEVu/usr/bin/…/…/lib/x86_64-linux-gnu/././…/…/usr/lib64/”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, “/tmp/.mount_commanVGEEVu/usr/bin/…/…/lib/x86_64-linux-gnu/././…/…/lib64/”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, “/tmp/.mount_commanVGEEVu/usr/bin/…/…/lib/x86_64-linux-gnu/././…/…/usr/lib/”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, “/tmp/.mount_commanVGEEVu/usr/bin/…/…/lib/x86_64-linux-gnu/././…/”, O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, “/tmp/.mount_commanVGEEVu/usr/bin/…/…/lib/x86_64-linux-gnu/./././”, O_RDONLY|O_CLOEXEC) = 4

I’m more than willing to dig down to the problem. But at this point I’m stumped about what to do, due to my inexperience working at the ELF level in linux. If you want to provide suggestions about how to proceed, I will follow them.

Ahh, no worries, I’ve discovered objdump, strings, readelf. I’ll see what I can figure out.

1 Like

The best advice I can give here is make full use of

  • (sudo) strace -f <yourapp> 2>&1 | grep <something>
  • LD_DEBUG=libs <yourapp>

Hi @probono , thanks.

strace -f is mysterious. I get this:

Cannot mount AppImage, please check your FUSE setup.
You might still be able to extract the contents of this AppImage
if you run it with the --appimage-extract option.
for more information

I did follow the OpenSuse directions in wiki, and it still reported this error. Most interestingly it did it not only for the “bad” appimage, but also for an appimage that works normally! So -f option did not help.

The LD_DEBUG is quite interesting. I tried it with libs, reloc, and versions. Everything looks wonderful (right paths into /tmp mount and so on) until they all, like strace, stop abruptly after is loaded (successfully, I might add, with an error of 0). I know that is the last in to load in this process because in your “-s deploy” version it is also the last to load in strace and then moves on to successfully run.

I don’t particularly think it is libbsd because it is the same in yours and in this test appimage.

The only thing I see that maybe is the problem is that my executable in the /tmp mounted appinage has the following entry:

INTERP 0x0000000000010f30 0x000000000040ff30 0x000000000040ff30
0x000000000000001c 0x000000000000001c R 0x1
[Requesting program interpreter: /lib64/]

I was under the impression that this was to be patched to look at:
/tmp/appimage-ld-linux… by AppRun and/or the hook lib. Isn’t that correct @azubieta?

Other than that I have gone through everything multiple times. The .env file looks good. The $ENVIRONMENT in the running app looks correct. The strace shows that everything is using the bundled (other than the initial openings of libc to initiate the run of the appimage and to, I’m supposing, get the local libc version). I can’t see any reason for this failure, which is an apparently related to somehow using the wrong libc despite all the pathing being to the correct libc.

The structure and files of the AppDir are correct, I’m certain. Probono’s “-s deploy” works perfectly even in Ubuntu 16.04, while this other appimage fails there and in OpenSuse which was originally a libc version problem.

Can I provide some files that maybe someone with a more practiced eye can look at? Let me know.

The commandoo3.AppImage is still available at the links above (in fact all the links are still good). The only thing left that I can think of is to patch my executable to the known path of the ld-linux file myself using appimagetool. If one of you thinks that is a good idea, or has a reason why the running appimage executable still points to /lib64/ld-linux, let me know.

Hi @probono & @azubieta. Problem SOLVED.

It was the fact that the payload was still pointing to interpreter in /lib64/… I patched my executable manually to the /tmp/ and it ran, with new failures, but it ran.

The failures were exceptions that I raised in my program. Internally I look to see if I can find ‘id’ and ‘which’, and my program shut down because it couldn’t find them. So, a new issue to track down but the program runs in this new failure mode in OpenSuse =and= in nixos =and= in ubuntu 16.04. Yea!

probono I found some irregularities and minor bugs in the go-appimage, as well as some new vars and the .env file routine. How should I share that with you?

Thanks for your patience, I know I write a lot, it is just how I roll. It is my equivalent of thinking out loud. Also I can then go back to my posts and see what I was thinking and/or found.

1 Like

Please open issues at

Thank you!

If you want to run it on an AppImage, you need to run sudo strace -f due to the way they are mounted with FUSE.

You will have to set this for every executable in the bundle.

Hi all, as far as I am concerned, this particular issue has been solved for now. Yay!

For anyone interested, please see:

1 Like