How to configure nano to set tab to 4 spaces except for Makefiles? - nano

Is there a way to tell nano use 4 spaces insead of TABs for every file except for Makefiles?

I use the following in my .bashrc file:
nano() {
[[ -n $1 ]] && [[ `basename "$1"` =~ (Makefile|makefile|GNUmakefile|.+\.mk) ]] && command nano --tabsize 2 "$#" || command nano --tabstospaces --tabsize 4 "$#"
}
The names checked are taken from the What Name to Give Your Makefile chapter of the GNU Make manual and are ordered according to their recommendations.
To keep things simple I only check the first argument. In my case this is sufficient as any other configuration settings are set in .nanorc (nb: you will need to remove set tabstospaces from .nanorc if present).
I've only used this with BASH 4.x and do not yet have enough experience with the shell to know whether I've used anything incompatible with earlier versions.
edit
Also consider the --ignorercfiles command line flag as a way to improve upon this.

Related

How to add EnvironmentFile directive to systemctl using Docker with centos7/httpd base image

I am not sure if this is possible without creating my own base image, but I use environment variables in /etc/environment on our servers and typically make them accessible to apache by doing the following:
$ printf "HTTP_VAR1=var1-value\n\
HTTP_VAR2=var2-value"\
>> /etc/environment
$ mkdir /usr/lib/systemd/system/httpd.service.d
$ printf "[Service]\n\
EnvironmentFile=/etc/environment"\
> /usr/lib/systemd/system/httpd.service.d/environment.conf
$ systemctl daemon-reload
$ systemctl restart httpd
$ reboot
The variables are then available in any PHP calls to getenv('HTTP_VAR1'); and etc. However, in running this from a docker file I get dbus errors on the systemctl commands. Without the systemctl commands it seems the variables are not available to apache as it seems the new EnvironmentFile directive doesn't take effect. My docker file snippet:
FROM centos/httpd:latest
RUN printf "HTTP_VAR1=var1-value\n\
HTTP_VAR2=var2-value"\
>> /etc/environment
RUN mkdir /usr/lib/systemd/system/httpd.service.d &&\
printf "[Service]\n\
EnvironmentFile=/etc/environment"\
> /usr/lib/systemd/system/httpd.service.d/environment.conf
RUN systemctl daemon-reload &&\
systemctl restart httpd
COPY entrypoint.sh /entrypoint.sh
So I happened upon the answer to the issue today. It seems that systemd drops backslashes inside single quotes, but it may effect double-quotes too from what I saw in testing. I found the systemd development mailing list thread from April 2014 where patching the issue was being discussed. It seems as though the fix never made it in. So we have to work around it.
In attempting to work around it I noticed some issues with actually reading the variables at all. It seemed as though either Apache or php-cli would get the correct variables, and sometimes not at all, it took a bit of sleuthing to figure out what was going on. Then I started reading into the systemd's EnvironmentFile directive to see if there was more to gain from the docs. It turns out it does not evaluate bash so export won't work. It expects a text file with variable assignments and herein lies one of the main issues that might keep this from being resolved.
I then devised a workable solution. Utilizing systemd's ExecStartPre directive I am able to run a script on startup of the httpd service. I then read in the environment file and write a new plain text one that will then be used by httpd's systemd unit. Here is the code:
Firstly, I moved my variables to /etc/profile.d/ directory rather than /etc/environment file.
file: /etc/profile.d/environment.sh
This is where we store all our environment variables, this gets easily sourced on all interactive shell logins. In the rarer cases where we need to have these variables available non-interactively we can either provide --login flag to /bin/bash or source it manually.
export HTTP_VAR1=var1-value-with-a-back\slash
export HTTP_VAR2=var2-value
file: /usr/lib/systemd/system/httpd.service.d/environment.conf
Our drop-in unit file to extend how the httpd service works. I add in a script that runs before httpd starts up. This gets ran on all httpd restarts and starts. The script that runs generates a plain text file at /etc/profile.d/environment.env which we subsequently tell systemd to load as an EnvironmentFile.
[Service]
ExecStartPre=/usr/bin/bash -c "/usr/local/bin/generate-plain-environment-file"
EnvironmentFile=/etc/profile.d/environment.env
file: /usr/local/bin/generate-plain-environment-file
Here is the script I am using, I whipped this together really fast, I really don't think it is that robust and it could be better. It just removes the export from the beginning of the lines and then escapes any backslashes since systemd drops single backslashes. A more proper solution might be to use bash to evaluate each line and obtain the variable value in case of usage of variables or other bash in the actual bash variables, then output them as plain text name=value assignments, however this is not part of my use-case so I didn't bother.
#!/bin/bash
cd /etc/profile.d/
rm -rf "./environment.env"
while IFS='' read -r line || [[ -n "$line" ]]; do
echo $(echo "${line}" | sed 's/^export //' | sed 's/\\/\\\\/g') >> "./environment.env";
done < "./environment.sh"
file: /etc/profile.d/environment.env
This is the resulting file generated by the described script.
HTTP_VAR1=var1-value-with-a-back\\slash
HTTP_VAR2=var2-value
Conclusion is that the I now have two files with the same thing in them but I only need to maintain the one, the other is generated each time we restart httpd. Also, we fix the backslash issue in the process. Hurray!

Shell redirection operation >|?

What is the difference between these two redirections?
[localhost ~]$ echo "something" > a_file.txt
[localhost ~]$ echo "something" >| a_file.txt
I can't seem to find any documentation about >| in the help.
>| overrides the noclobber option in the shell (set with $ set -o noclobber, indicates that files can not be written over).
Basically, with noclobber, you get an error if you try to overwrite an existing file using >:
$ ./program > existing_file.txt
bash: existing_file.txt: cannot overwrite existing file
$
Using >| will override that error and force the file to be written over:
$ ./program >| existing_file.txt
$
It's analogous to using the -f or --force option on many shell commands.
From the Bash Reference Manual Section "3.6.2 Redirecting Output":
If the redirection operator is >, and the noclobber option to the set builtin has been enabled, the redirection will fail if the file whose name results from the expansion of word exists and is a regular file. If the redirection operator is >|, or the redirection operator is > and the noclobber option is not enabled, the redirection is attempted even if the file named by word exists.
Searching for "bash noclobber" generally brings up articles that mention this somewhere. See this question on SuperUser, this section in O'Reilly's "Unix Power Tools", and this Wikipedia article on Clobbering for examples.

Debian package:user and group

Recently,I use cmake/cpack to make a debian package.I make succeed.But I install it on the computer(sudo dpkg -i mypcakge.deb), I find a problem: the install program's user and group is root:root.Due to some reason, my problem should run in a specific user/group. I don't know how to do this, could you help me?
Also, I don't want to modify the user and group with chown(..) after I installed the package.Is there a way to add something in the CMakeLists to do this?
It is not related only to CMake, but in general when using debhelper and/or non-standard usernames.
dh(1) often used in debian/rules by default will call dh_fixperms(1), which will reset owners and permissions by default.
There are basically three ways to retain owners/permissions you want:
if you use some standard Debian system user/group, you may skip
or override dh_fixperms(1) and you may specify files to override owner/group for. Be sure that your package pre-depends on correct version of base-passwd package which contains wanted users/groups.
You could override in your debian/rules like here (see dh_fixperms(1) man page):
override_dh_fixperms:
dh_fixperms --exclude matchname
Debian docs have more info.
if you create your own users and you want files/dirs to be owned by them, you will need to use postinst script. In it, you first need to create users/groups if they don't already exist, and then do something like
chown myuser:mygroup /var/log/mydir
chmod 0750 /var/log/mydir
Alternatively, you can use (also in your postinst and postrm scripts) dpkg-statoverride(8) to change owners,groups and permissions of your (or other) files like this:
for i in /usr/bin/foo /usr/sbin/bar; do
# only do something when no setting exists
if ! dpkg-statoverride --list $i >/dev/null 2>&1; then
#include: debconf processing, question about foo and bar
if [ "$RET" = "true" ] ; then
dpkg-statoverride --update --add sysuser root 4755 $i
fi
fi
done
You should also handle removal, like this:
for i in /usr/bin/foo /usr/sbin/bar; do
if dpkg-statoverride --list $i >/dev/null 2>&1; then
dpkg-statoverride --remove $i
fi
done

How can I cat back exact formatting regardless of shell?

While trying to write a script, I found an interesting issue with cat today. If I do the following at the command line, everything works properly:
var=$(ssh user#server "cat /directory/myfile.sh")
echo $var > ~/newfile.sh
This works and I have a script file with all the proper formatting and can run it. However, if I do the EXACT same thing in a script:
#!/bin/sh
var=$(ssh user#server "cat /directory/myfile.sh")
echo $var > ~/newfile.sh
The file is mangled with carriage returns and weird formatting.
Does anyone know why this is happening? My goal is to ultimately cat a script from a server and run it locally on my machine.
EDIT
I now know that this is happening because of my invoking #!/bin/sh in my shell script. The command line works because I'm using zsh and it is preserving the formatting.
Is there a way to cat back the results regardless of the shell?
As you seem to have figured out, word splitting is off by default on zsh, but on in sh, bash, etc. You can prevent word splitting in all shells by quoting the variable:
echo "$var" > ~/newfile.sh
Note that echo appends a newline to its output by default, which you can suppress (on most echo implementations and builtins) with -n.

Updating files after RVM install

I have installed RVM enroute to updating and running different ruby and rails. After install I received message to update shell's loading files.
1) Place the folowing line at the end of your shell's loading files
(.bashrc or .bash_profile for bash and .zshrc for zsh),
after all PATH/variable settings:
[[ -s "/Users/eric/.rvm/scripts/rvm" ]] && source "/Users/eric/.rvm/scripts/rvm" # This loads RVM into a shell session.
You only need to add this line the first time you install rvm.
I typed [[ -s "/Users/eric/.rvm/scripts/rvm" ]] && source "/Users/eric/.rvm/scripts/rvm"
and hit enter. Does this update my files? Or do I have to open some type of file and cut and paste code?
Since I did not see any notice as stated below from part 2 of the post install, I closed the shell and opened a new one. but the RVM command does not seem to work. Part 2 of the instructions post install was:
2) Ensure that there is no 'return' from inside the ~/.bashrc file,
otherwise rvm may be prevented from working properly.
This means that if you see something like:
'[ -z "$PS1" ] && return'
then you change this line to:
if [[ -n "$PS1" ]] ; then
# ... original content that was below the '&& return' line ...
fi # <= be sure to close the if at the end of the .bashrc.
# This is a good place to source rvm v v v
[[ -s "/Users/eric/.rvm/scripts/rvm" ]] && source "/Users/eric/.rvm/scripts/rvm" # This loads RVM into a shell session.
EOF - This marks the end of the .bashrc file
Be absolutely *sure* to REMOVE the '&& return'.
If you wish to DRY up your config you can 'source ~/.bashrc' at the bottom of your .bash_profile.
Placing all non-interactive (non login) items in the .bashrc,
including the 'source' line above and any environment settings.
Thanks for the help as I am very new and trying to learn RoR but so far have not been able to get past the setup in many of the tutorials I've attempted. It seems many [
1 2 are out of date with new software or I get error messages before I can even attempt to learn the code. If someone knows of a good beginner tutorial that would be great. Thanks again!
The snippet that the installer gives you need to go in a file called the bashrc. The file lives in your home directory: /Users/eric/.bashrc
You need to edit this file and add the line from rvm and then you should be good to go.
As for getting rolling with rails I'd recommend The Pragmatic Programmers book on rails. You can find their books at pragprog.com
If you're on Ubuntu, my tutorial on setting rvm will get you roll all the way up to rails installation:
http://blog.dcxn.com/2011/06/20/setting-up-rvm-on-ubuntu-11-04/