Makefile docker command with single quote failling - bash

With this in a Makefile:
single:
docker network inspect -f '{{ .IPAM }}' web-proxy
double:
docker network inspect -f "{{ .IPAM }}" web-proxy
make single fails with make: docker: Permission denied while make double succeeds. Both commands work if I input them directly in my bash.
It happens only since I upgraded to Ubuntu 22.04.1 (from the 22.04). I have docker 20.10.20, bash 5.1.16 and GNU Make 4.3
Any idea were it can come from ? From what I have read the Makefile doesn't care about quotes: https://stackoverflow.com/a/23332194

I don't know why updating your system made a difference, but this is almost certainly related to a bug in gnulib (that GNU make uses).
If you add a semicolon to the end of the docker command line in the single target I'll bet it will work again.
The bug is this: if some directory on your PATH contains a subdirectory with the name of a command you want to invoke, then if make attempts to run that command directly (without using a shell) it will fail because it tries to "run" that directory. So for example if you have /my/dir in PATH and the directory /my/dir/docker/. exists, you will get this error (for simple docker commands).
The "double" target works because (due to the {{) make's trivial parser decides that this command it not "simple enough" to parse directly, and it runs the shell to do it; the shell doesn't get confused by that directory.
You can (1) add the semicolon as above, or (2) figure out why some directory on your PATH contains a docker subdirectory and remove it.
The next release of GNU make (probably released by the end of the month) will fix this issue (includes a newer version of the gnulib module, with the fix).

Related

write to file is empty when I write from within a docker img

The code below is some step that is part of a MakeFile which is executed when a certain stage is run in ci/cd.
.PHONY:deploy_endpoint_configuration
deploy_endpoint_configuration:
#echo Deploying endpoint configuration
gcloud endpoints services deploy ocr/model_adapter/predict_contracts.yaml --project $(project) &> $(project_dir)/deploy_contract.txt
cat $(project_dir)/deploy_contract.txt | grep -Eo '\d*-\d*-\w*' | tail -n1 > $(project_dir)/config_id.txt
What I'm experiencing is that the content of deploy_contract.txt etc is always empty when this piece of code is executed in the pipeline (e.g. GitLab). I don't understand why? Has this to do w/ the fact that MakeFile executes a new shell for every command? Not entirely sure though, and yet this is hard to debug. I do confirm this issue when I run it as followed: gitlab-runner exec docker -here the stage- (for local debug purpose). But when I run it locally on macOS (i.e. only execute make deploy_endpoint_configuration), thus it's not wrapped in a container as before, it runs and functions like it should (read as the content of config_id and deploy_contract is not empty but contains the stdout + errorout)
for reference:
image used in the ci/cd stage = image: dsl.company.com:5000/python:3.7-buster
on top of that gcloud cli is installed to make use of gcloud commands.
Anyone an idea to why no content is written to my files? (it's for sure deploying though - so there must be something)
My suspicion is that it's because your command script relies on bash features. GNU make will always run /bin/sh as its shell. On some systems (like RedHat and RedHat-derived systems) /bin/sh is actually a link to bash and so makefile recipes that use bash-specific features will work. I believe MacOS does the same, although I don't do Mac.
On other systems, like Debian and Debian-derived systems like Ubuntu, /bin/sh is a simple, fast POSIX-compliant shell like dash, which doesn't support fancy bash things and so makefile recipes that use bash-specific features will not work.
Probably your container image is one of the latter type, while MacOS (your local system) uses bash as the shell.
You are using &> which is a bash-specific feature, that is not supported by POSIX shells.
You should write this using POSIX syntax, which is >$(project_dir)/deploy_contract.txt 2>&1
Either that or you can try overriding the shell in your makefile:
SHELL := /bin/bash
to force make to run bash instead... this will work as long as the container image you're running does actually have bash in it.

Trouble installing haskell: how to adjust PATH variable to add to a shell config file?

I installed Haskell on my MacOS system using ghcup installer. It worked because if I type ghci I am dropped into this interactive shell. However I got this message in the terminal after doing the install:
In order to run ghc and cabal, you need to adjust your PATH variable.
You may want to source '/Users/user1/.ghcup/env' in your shell
configuration to do so (e.g. ~/.bashrc).
Detected bash shell on your system...
If you want ghcup to automatically add the required PATH variable to "/Users/user1/.bashrc"
answer with YES, otherwise with NO and press ENTER.
YES
grep: /Users/user1/.bashrc: No such file or directory
My shell is bash 3.2 But as you can see, when I typed YES it says there is no such file. How do I find my shell configuration file, or resolve this? I'd like to complete the setup correctly here.
And I have to be honest about my level of knowledge here, I don't truly understand what this is asking exactly. Is the PATH variable 'env'?
On macOS, .bashrc does not exist by default. ghcup will create this file, so the command you ran will have worked correctly. However, one of ghcup's subcommands expected to find the file before it was created, and therefore reported that error message. You can safely ignore this.

ZSH doesn't identify "*" as "all files"

I use ZSH shell environment (with 'oh-my-zsh' plugin) on my Ubuntu 18.04 and I have noticed an issue with it. I think my ZSH shell doesn't identify * sometimes as "all files".
For example if I wanted to install all ROS packages with the prefix control I would enter the command : sudo apt-get install ros-melodic-control* and this should work and install all ROS Melodic packages starting with control from the main ROS repository. This thing worked when I used BASH earlier. But now when I do the same thing in ZSH it gives me the following error : zsh: no matches found: ros-melodic-control*
It would be great if someone helped me identify the exact problem.
TIA
It's the difference between zsh and bash. zsh never will run a command that contains wildcard pattern that doesn't match existing files. Bash will execute as is.
It also may fail differently. If look-up would return anything that matches the pattern, , eg. a file named ros-melodic-control.pdf, zsh will execute sudo apt-get install ros-melodic-control.pdf. NB: wildcards always are investigated by the shell.
Consider it be a paranoid shell for non-root users who primarily interact only with file system. To actually do what you want you have to use single quotes.
sudo apt-get install 'ros-melodic-control*'
Packages given as argument to apt-get aren't files. they are names in database which also contains their location (local cache in /var, disk, remote server or NFS source). SO you have to ensure they are passed as string if you use wildcards. Just with bash\sh\ksh you can get away without quotes if you have no matching files.
Adding quotes would pass enclosed text "as-is" to arguments of executed program, as a string. Therefore apt-get will receive string ros-melodic-control* and will search for packages that matches it. Without quotes shell will try to expand wildcards.

How to run Shell Script using CHMOD in a folder [duplicate]

I simply want to run an executable from the command line, ./arm-mingw32ce-g++, but then I get the error message,
bash: ./arm-mingw32ce-g++: No such file or directory
I'm running Ubuntu Linux 10.10. ls -l lists
-rwxr-xr-x 1 root root 433308 2010-10-16 21:32 arm-mingw32ce-g++
Using sudo (sudo ./arm-mingw32ce-g++) gives
sudo: unable to execute ./arm-mingw32ce-g++: No such file or directory
I have no idea why the OS can't even see the file when it's there. Any thoughts?
This error can mean that ./arm-mingw32ce-g++ doesn't exist (but it does), or that it exists and is a dynamically linked executable recognized by the kernel but whose dynamic loader is not available. You can see what dynamic loader is required by running ldd /arm-mingw32ce-g++; anything marked not found is the dynamic loader or a library that you need to install.
If you're trying to run a 32-bit binary on an amd64 installation:
Up to Ubuntu 11.04, install the package ia32-libs.
On Ubuntu 11.10, install ia32-libs-multiarch.
Starting with 12.04, install ia32-libs-multiarch, or select a reasonable set of :i386 packages in addition to the :amd64 packages.
I faced this error when I was trying to build Selenium source on Ubuntu. The simple shell script with correct shebang was not able to run even after I had all pre-requisites covered.
file file-name # helped me in understanding that CRLF ending were present in the file.
I opened the file in Vim and I could see that just because I once edited this file on a Windows machine, it was in DOS format. I converted the file to Unix format with below command:
dos2unix filename # actually helped me and things were fine.
I hope that we should take care whenever we edit files across platforms we should take care for the file formats as well.
This error may also occur if trying to run a script and the shebang is misspelled. Make sure it reads #!/bin/sh, #!/bin/bash, or whichever interpreter you're using.
I had the same error message when trying to run a Python script -- this was not #Warpspace's intended use case (see other comments), but this was among the top hits to my search, so maybe somebody will find it useful.
In my case it was the DOS line endings (\r\n instead of \n) that the shebang line (#!/usr/bin/env python) would trip over. A simple dos2unix myfile.py fixed it.
I found my solution for my Ubuntu 18 here.
sudo dpkg --add-architecture i386
Then:
sudo apt-get update
sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386
I got this error “No such file or directory” but it exists because my file was created in Windows and I tried to run it on Ubuntu and the file contained invalid 15\r where ever a new line was there.
I just created a new file truncating unwanted stuff
sleep: invalid time interval ‘15\r’
Try 'sleep --help' for more information.
script.sh: 5: script.sh: /opt/ag/cont: not found
script.sh: 6: script.sh: /opt/ag/cont: not found
root#Ubuntu14:/home/abc12/Desktop# vi script.sh
root#Ubuntu14:/home/abc12/Desktop# od -c script.sh
0000000 # ! / u s r / b i n / e n v b
0000020 a s h \r \n w g e t h t t p : /
0000400 : 4 1 2 0 / \r \n
0000410
root#Ubuntu14:/home/abc12/Desktop# tr -d \\015 < script.sh > script.sh.fixed
root#Ubuntu14:/home/abc12/Desktop# od -c script.sh.fixed
0000000 # ! / u s r / b i n / e n v b
0000020 a s h \n w g e t h t t p : / /
0000400 / \n
0000402
root#Ubuntu14:/home/abc12/Desktop# sh -x script.sh.fixed
As mentioned by others, this is because the loader can't be found, not your executable file. Unfortunately the message is not clear enough.
You can fix it by changing the loader that your executable uses, see my thorough answer in this other question: Multiple glibc libraries on a single host
Basically you have to find which loader it's trying to use:
$ readelf -l arm-mingw32ce-g++ | grep interpreter
[Requesting program interpreter: /lib/ld-linux.so.2]
Then find the right path for an equivalent loader, and change your executable to use the loader from the path that it really is:
$ ./patchelf --set-interpreter /path/to/newglibc/ld-linux.so.2 arm-mingw32ce-g++
You will probably need to set the path of the includes too, you will know if you want it or not after you try to run it. See all the details in that other thread.
I got the same error for a simple bash script that wouldn't have 32/64-bit issues. This is possibly because the script you are trying to run has an error in it. This ubuntu forum post indicates that with normal script files you can add sh in front and you might get some debug output from it. e.g.
$ sudo sh arm-mingw32ce-g++
and see if you get any output.
In my case the actual problem was that the file that I was trying to execute was in Windows format rather than Linux.
Below command worked on 16.4 Ubuntu
This issue comes when your .sh file is corrupt or not formatted as per unix protocols.
dos2unix converts the .sh file to Unix format!
sudo apt-get install dos2unix -y
dos2unix test.sh
sudo chmod u+x test.sh
sudo ./test.sh
I had the same problem with a file that I've created on my mac.
If I try to run it in a shell with ./filename I got the file not found error message.
I think that something was wrong with the file.
what I've done:
open a ssh session to the server
cat filename
copy the output to the clipboard
rm filename
touch filename
vi filename
i for insert mode
paste the content from the clipboard
ESC to end insert mode
:wq!
This worked for me.
Added here for future reference (for users who might fall into the same case):
This error happens when working on Windows (which introduces extra characters because of different line separator than Linux system) and trying to run this script (with extra characters inserted) in Linux. The error message is misleading.
In Windows, the line separator is CRLF (\r\n) whereas in linux it is LF (\n). This can be usually be chosen in text editor.
In my case, this happened due to working on Windows and uploading to Unix server for execution.
I just had this issue in mingw32 bash. I had execuded node/npm from Program Files (x86)\nodejs and then moved them into disabled directory (essentially removing them from path). I also had Program Files\nodejs (ie. 64bit version) in path, but only after the x86 version. After restarting the bash shell, the 64bit version of npm could be found. node worked correctly all the time (checked with node -v that changed when x86 version was moved).
I think bash -r would've worked instead of restarting bash: https://unix.stackexchange.com/a/5610
I had this issue and the reason was EOL in some editors such as Notepad++. You can check it in Edit menu/EOL conversion. Unix(LF) should be selected.
I hope it would be useful.
Hit this error trying to run terraform/terragrunt (Single go binary).
Using which terragrunt to find where executable was, got strange error when running it in local dir or with full path
bash: ./terragrunt: No such file or directory
Problem was that there was two installations of terragrunt, used brew uninstall terragrunt to remove one fixed it.
After removing the one, which terragrunt showed the new path /usr/bin/terragrunt everything worked fine.
For those encountering this error when running a java program, it's possible that you're trying to run a 64-bit java program using on a 32-bit linux operating system.
I only realised when I ran ldd on 64-bit java which reported:
ldd /usr/java/jdk1.8.0_05/bin/java
'not a dynamic executable'
Whereas the old 32 bit java reported sensible results:
ldd /usr/java/jdk1.8.0_05/bin/java
In my case, it turns out the file was a symlink:
$ cat deluge-gtk.lock
cat: deluge-gtk.lock: No such file or directory
$ file deluge-gtk.lock
deluge-gtk.lock: broken symbolic link to 32309
Misleading errors like this are fairly common on Linux. Related discussion: https://lwn.net/Articles/532771/
Give it a try by changing the name of file or folder which is not showing in terminal/command prompt.
step1 : change the name of file or folder.
step2 : cd filename/foldername
For future readers, I had this issue when trying to launch a Django server using gunicorn. I was using AWS CodeBuild to build the virtual environment and run tests and using CodeDeploy to put the built artifacts onto the production server and launch the new version (all environments were Ubuntu 20.04). I had mistakenly thought that env/bin/... contained actual binaries of native libraries but that was not the case. It was just Python scripts with a shebang of the path to the Python interpreter on the build machine. In my case, the machine installing the packages and actually running the packages was different. To be more specific, all of the files in env/bin had the shebang #!/codebuild/output/src715682316/src/env/bin/python, so of course running env/bin/gunicorn on the production server would fail. The cryptic error message was when Ubuntu would tell me that env/bin/gunicorn didn't exist as opposed to saying /codebuild/output/src715682316/src/env/bin/python didn't exist. I was able to fix this problem by starting gunicorn using python3 env/bin/gunicorn instead of env/bin/gunicorn.
In a .sh script, each line MUST end with a single character - newline (LF or "\n").
Don't make mistakes like me, because my text-editor of choice is Notepad++ in Win.

cron: run a script that sources a function

I have script that does a bunch of stuff. It sources a bunch of functions that are in the directory the script is being run from. i.e.
/home/me/script.sh
/home/me/function1
/home/me/function2
If I cd into /home/me and run ./script.sh everything works fine. The functions are sourced and do what needs to be done.
However, if I try to run this as a cron job, it will run up until the point I am trying to source the functions, and then it just stops and the process is terminated (if I run it directly from the directory, at least I get some errors).
Like wise, if I try to run this from another directory, I get a bunch of errors. e.g.
cd /opt/
/home/me/script.sh
function1: command not found
function2: command not found
I'm sure this has something to do with environmental variables, but I have no idea which ones. I have tried setting (in crontab):
PATH=/home/me
SHELL=/bin/bash
But that doesn't work either. Any help is appreciated. I don't want to hard code in the paths to the functions, and instead make them relative to the path the script is in (preferably the same dir).
Please let me know if you need any more information.
You are most probably aware of this, but just to be clear: A shell function does not have a path. They just need to be loaded into the current shell by sourcing the script that contains them:
source /path/to/functions
or
cd /path/to/functions
source functions
If you are talking about shell programs (scripts) instead, then you need to account for the fact that on Unix-like OS, the current directory is never in the PATH by default:
/path/to/functions/function1
or
cd /path/to/functions
./function1
You tagged your question Bash, but note that to be POSIX-compatible (e.g. if using sh), you have to use the . keyword (instead of either . or source on Bash) and the same restrictions regarding the PATH as for command execution apply, see dot:
. ./function1

Resources