How to fix «exec user process caused no such file or directory»
I’m trying to use tini in my Dockerfile but I’m getting an error. I used the code example from the tini readme file.
# . code which builds /app/foo # Add Tini ENV TINI_VERSION v0.18.0 ADD https://github.com/krallin/tini/releases/download/$/tini /tini RUN chmod +x /tini ENTRYPOINT ["/tini", "--"] # Run the program when the container starts CMD ["/app/foo"]
I expect my program to run without having PID=1 but instead I get: standard_init_linux.go:207: exec user process caused «no such file or directory» EDIT: /app/foo is created in the beginning of the Dockerfile. There is no problem with /app/foo . As proof of this, if I comment out the ENTRYPOINT line (or remove all the tini related code), my /app/foo runs fine except for the fact that it has PID=1
Wrong architecture; the thing that gets downloaded is actually a tar file or HTML page; missing shared libraries (especially if you’re running on a scratch image without a libc); .
3 Answers 3
Another cause: incorrect line ends in the file. Linux expects LF s, and if your host is Windows, the script you want to run will have CRLF s.
Another cause could be that a script is called for which the first line points to an unavailable shell. For example, when the first line of the script (also known as the shebang) is
Then this requires bash on the system. Changing bash to the default sh(ell) for the system can be a solution. So, replace by
Alternatively, on some systems bash is not in /bin , but in /usr/bin/env . So, replace by
As David mentions, you need to check what is getting downloaded. If you run this by hand in an Alpine image, you’ll see the exact issue:
$ docker run -it --rm alpine /bin/sh / # apk add file . / # apk add curl . / # curl -sSL https://github.com/krallin/tini/releases/download/v0.18.0/tini >tini / # chmod 755 tini / # file tini tini: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=38c262787814dc459678c8f24710bbde944b7e56, stripped / # ldd tini /lib64/ld-linux-x86-64.so.2 (0x7f1beab2a000) libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7f1beab2a000) Error relocating tini: __fprintf_chk: symbol not found / # ./tini /bin/sh: ./tini: not found / # ls -al /lib64/ld-linux-x86-64.so.2 ls: /lib64/ld-linux-x86-64.so.2: No such file or directory
Note the dynamically linked part, and the fact that it is looking for libc. The error in an Alpine scenario is telling you that libc doesn’t exist. You’d also see this with a scratch image.
You’ll want to either get a version of tini that is completely statically compiled, or switch to a system with libc installed. For the former, with tini, that’s as easy as downloading a different URL:
ADD https://github.com/krallin/tini/releases/download/$/tini-static /tini
php exec bash scripts : No such file or directory
I have a few bash and perl scripts which has been asked to be made executable through a web based interface. Nothing fancy, just for easy access. PHP seemed to be the quick and dirty solution for the purpose [through exec() ]. So I turned off the safe mode in php.ini and tried
$output = array(); exec('/var/www/vhosts/default/htdocs/scripts/RUN.sh',$OUTPUT); print_r($output); var_dump($output);
Now whatever files are accessed in the RUN.sh script (accessed though a relative path) are not found. Is there any way of getting this to work without giving complete path to every single redirect (or any file for that matter) that is being accessed in the scripts? After applying the accepted solution: Say one line form the script:
time python idsplitter.py OUTPUT/TMP/tokens OUTPUT/token_splits echo "done"
While the time -s output gets pushed to error_log file, «done» is never passed to the $OUTPUT array. The returned value in the third argument to exec(), when printed on page gives 0 . Update: time command puts it out to stderr so if do `
you should set the working directory for RUN.sh . you can use chdir before exec or use exec cd WORKING_DIRECTORY; ./RUN.sh .
2 Answers 2
Change the current working directory as part of the script itself.
Your working directory, from the perspective of the RUN.sh script, isn’t what you think it is. Therefore, relative paths in the script don’t point where intended.
To fix it you need to force the current working directory to be the one that works with the relative paths. So, either:
- use absolute paths, or
- change the current working directory via calling cd [/absolute/path] in the RUN.sh script, to force it to be correct.
Aah. ehhh.. I’m almost there . there’s a time in the RUN.sh whose output should go to the webpage. But it doesn’t work that way, the output gets redirected to /var/log/httpd/error_log . It keeps printing Array ( ) array(0) < >as if nothing has happened!
Can you execute a chdir(2) call in your PHP script immediately before your exec() call to get the results you want? Or would that upset your PHP interpreter too much? (With CGI scripts, it’d be no problem at all; but FastCGI or similar mechanisms might not like you much.)
Relying on relative pathnames is already a bit quick-and-dirty, and this just perpetuates it. Perhaps fixing the scripts is a better approach.
I’m stuck with the output getting redirected to the error_log rather than to the php page, any idea why?
That is a symptom of a program sending its output to standard error, rather than standard out.
But there is a complication with time — normally, when you run time , you get the bash(1) built-in time reserved keyword. I cannot find any easy way to ask bash(1) to send the time reserved keyword output to a different file descriptor. However, you can also run the time(1) program (which is in /usr/bin/time ). By default, time(1) ‘s output goes to standard error, but you may redirect output as you wish:
$ /usr/bin/time echo hello hello 0.00user 0.00system 0:00.00elapsed ?%CPU (0avgtext+0avgdata 2528maxresident)k 0inputs+0outputs (0major+206minor)pagefaults 0swaps $ /usr/bin/time echo hello > /dev/null 0.00user 0.00system 0:00.00elapsed ?%CPU (0avgtext+0avgdata 2544maxresident)k 0inputs+0outputs (0major+207minor)pagefaults 0swaps $ /usr/bin/time echo hello > /dev/null 2&>1 $
To get the time(1) output to look more like the time shell built in keyword output, you can use the -p option:
$ /usr/bin/time -p echo hello hello real 0.00 user 0.00 sys 0.00
time python idsplitter.py OUTPUT/TMP/tokens OUTPUT/token_splits
/usr/bin/time -p python idsplitter.py OUTPUT/TMP/tokens OUTPUT/token_splits 2>&1
and you ought to be good to go.