Why is capistrano interpreting a flag passed with a command to `run` as input? - ruby-on-rails

I'm trying to do this:
run "echo -n 'foo' > bar.txt"
and the contents of bar.txt ends up being:
-n foo \n
(With \n representing an actual newline)
I use run for other commands like rm -rf and, to my knowledge, it works fine.

I just found this in man echo:
Some shells may provide a builtin echo command which is similar or identical to this utility. Most notably, the builtin echo in sh(1) does not accept the -n option. Consult the builtin(1) manual page.
My version of bash has an echo builtin but seems to be respecting the -n flag. It looks like the shell on your deployment machine doesn't, in which case using the full path to the echo binary might do what you want here:
run "/bin/echo -n 'foo' > bar.txt"

It appears as though the -n flag isn't being interpreted as a flag by the shell. If, from the command line, one executes echo -Y hi, the output will be -Y hi.

Related

How to see the PATH inside a shell without opening a shell

Use the command flag looked like a solution but it doesn't work
Inside the following shell:
nix shell github:nixos/nixpkgs/nixpkgs-unstable#hello
the path contain a directory with an executable hello
I've tried this:
nix shell github:nixos/nixpkgs/nixpkgs-unstable#hello --command echo $PATH
I can't see the hello executable
My eyes are not the problem.
diff <( echo $PATH ) <( nix shell github:nixos/nixpkgs/nixpkgs-unstable#hello --command echo $PATH)
It see no difference. It means that the printed path doesn't not contains hello.
Why?
The printed path does not contain hello because if your starting PATH was /nix/var/nix/profiles/default/bin:/run/current-system/sw/bin, then you just ran:
nix shell 'github:nixos/nixpkgs/nixpkgs-unstable#hello' --command \
echo /nix/var/nix/profiles/default/bin:/run/current-system/sw/bin
That is to say, you passed your original path as an argument to the nix shell command, instead of passing it a reference to a variable for it to expand later.
The easiest way to accomplish what you're looking for is:
nix shell 'github:nixos/nixpkgs/nixpkgs-unstable#hello' --command \
sh -c 'echo "$PATH"'
The single quotes prevent your shell from expanding $PATH before a copy of sh invoked by nix is started.
Of course, if you really don't want to start any kind of child shell, then you can run a non-shell tool to print environment variables:
nix shell 'github:nixos/nixpkgs/nixpkgs-unstable#hello' --command \
env | grep '^PATH='

Access files written in docker volumes from the host

I have a docker container writing logfiles to a name volume.
From the host I want to analyce the logfiles and search for given log messages. But when I access the folder which 'docker inspect VOLUMNAME' gives, I get strange behavior, which I do not understand.
e.g. following command does give empty lines as output:
user#docker-host-01:~/docker-server-env/otaya-designdb$ sudo bash -c "for logfile in /var/lib/docker/volumes/design-db-logs/_data/*/*; do echo ${logfile}; done"
user#docker-host-01:~/docker-server-env/otaya-designdb$
What could be the reason?
Your local shell is expanding the variable expansion inside the double quotes before the loop happens. Change the double quotes to single quotes.
That is, when you run
sudo bash -c "for ... ; do echo ${logfile}; done"
first your local shell replaces the variable reference with whatever your local environment has set for $logfile, probably nothing
sudo bash -c 'for ...; do echo ; done'
and then it runs that command. If you change this to single quotes initially
sudo bash -c 'for ... ; do echo ${logfile}; done'
it will avoid this expansion.
You can see this just by putting the word echo at the front of the command: the shell will do its expansion, and then echo will print out the command that would have run.

Iterate in RUN command in Dockerfile

I have a line that looks something like:
RUN for i in `x y z`; do echo "$i"; done
...with the intention of printing each of the three items
But it raises /bin/sh: 1: x: not found
Any idea what I'm doing wrong?
It looks like you're using backticks. What's in backticks gets executed and the text in the backticks gets replaced by what's returned by the results.
Try using single quotes or double quotes instead of backticks.
Try getting rid of the backticks like so:
RUN for i in x y z; do echo "$i"; done
I would suggest an alternative solution of this.
In stead of having the LOOP inside docker file, can we take a step back ...
Implement the loop inside a independent bash script;
Which means you would have a loop.sh as following:
#!/bin/bash
for i in $(seq 1 5); do echo "$i"; done
And in your Dockerfile, you will need to do:
COPY loop.sh loop.sh
RUN ./loop.sh
With the approach aboved it requires one extra step and costs one extra layer.
However, when you are going to do some more complicated stuff, I would recommend to put them all into the script.
All the operations inside the script will only cost one layer.
To me this approach is could be cleaner and more maintainable.
Please also have a read at this one:
https://hackernoon.com/tips-to-reduce-docker-image-sizes-876095da3b34
For a more maintainable Dockerfile, my preference is to use multiple lines with comments in RUN instructions especially if chaining multiple operations with &&
RUN sh -x \
#
# execute a for loop
#
&& for i in x \
y \
z; \
do \
echo "$i"
done \
\
#
# and tell builder to have a great day
#
&& echo "Have a great day!"
Run Docker container perpetually by writing a simple script
docker run -d <container id> \
sh -c "while :; do echo 'just looping here... nothing special'; sleep 1; done"
We can do it like
RUN for i in x \y \z; do echo "$i" "hi"; done
output of above command will be
x hi
y hi
z hi
Mind spaces while writing - for i in x \y \z;
example - snippet from git bash

How to use Fred's ImageMagick textcleaner script?

I want to do OCR on some of my images, but images are not quite very impressive. So, for cleaning it I wanted to use Fred's ImageMagick Textcleaner script. Command that I gave:-
sh textcleaner.sh input_file output_file -g -e stretch -f 25 -o 20 -t 30 -u -s 1 -T -p 20
This is the arguments which Fred has given on website itself. I am also doing for same sample image. But I don't think so any of my options are working everything is by default. And I keep getting this error also
textcleaner.sh: line 177: type: textcleaner.sh: not found
usage: dirname path
usage: basename string [suffix]
basename [-a] [-s suffix] string [...]
And At last I had to keep the files in same folder where my textcleaner script is. How can I make it global and give the absolute path to it rather than putting the files wherever textcleaner is.
It's a bash script - it says so in the first line - yet you are trying to run it in sh - which is not bash. You need to make the script executable, by running
chmod +x textcleaner
then you can run it properly using:
./textcleaner ... arguments ...
That should make the error message go away. Then try showing us a sample image so we can try and see what the problem is.
In my ImageMagick scripts, the syntax is script name ...arguments... input output. So your command should be
bash textcleaner.sh -g -e stretch -f 25 -o 20 -t 30 -u -s 1 -T -p 20 input_file output_file
See my Pointers For Use (for further configuration) at my home page: http://www.fmwconcepts.com/imagemagick/index.php

How to run a command on the startup of an xterm?

How can I run a command on xterm startup i.e. when an xterm terminal is launched a the command is already executed?
I have edited the .bashrc file to add this line:
xterm "ls"
But this does not work.
Please suggest what should I do to acheive this.
Thanks.
According to the bash manual, ~/.bashrc is used for interactive shells. xterm runs a shell, so perhaps your "does not work" causes a chain of xterm's.
The xterm program sets these environment variables which are useful for scripting: XTERM_VERSION and XTERM_SHELL. In your ~/.bashrc file, you could use the former to run the xterm -ls once only:
if [[ -z "$XTERM_VERSION" ]]
then
xterm -hold -e ls &
fi
which seems to be what you are asking for:
it would run an xterm if not run from an existing xterm
it prevents the xterm from closing when the ls is done.
A more useful-seeming way of showing an ls on shell startup would be to run ls in each shell as it is started (for that case, you do not need run a separate xterm). Again, you can use environment variables to do this once (in case you run bash to make a subshell):
if [[ -z "$XTERM_ONCE" ]]
then
export XTERM_ONCE=$(date)
ls
fi
I use this:
-e /bin/bash -login
-e command [arguments]
Run the command with its command-line arguments in the rxvt window;
also sets the window title and icon name to be the basename of the
program being executed if neither -title (-T) nor -n are given on the
command line. If this option is used, it must be the last on the
command-line. If there is no -e option then the default is to run the
program specified by the SHELL environment variable or, failing that,
sh(1).
http://linux.die.net/man/1/rxvt

Resources