#!/bin/bash # This script auto delete the current instance and ask the # Autoscale Group to replace the node ########################################################### CRED_FILE=/opt/autoscale/.credentials AS_GRP_ID=a17b08b3-0c04-48e8-84a9-3070c29a27fa ########################################################### # Gather info from credential file USERNAME=$(grep username $CRED_FILE | awk -F= '{print $2}' | sed 's/ //g') APIKEY=$(grep api_key $CRED_FILE | awk -F= '{print $2}' | sed 's/ //g') REGION=$(grep region $CRED_FILE | awk -F= '{print $2}' | sed 's/ //g' | tr '[:upper:]' '[:lower:]') SERVER_UID=$(xenstore-read name | sed 's/instance-//') AUTH=$( curl -sd \ "{ \"auth\": { \"RAX-KSKEY:apiKeyCredentials\": {\"username\": \"$USERNAME\", \"apiKey\": \"$APIKEY\"} } }" \ -H 'Content-Type: application/json' \ 'https://identity.api.rackspacecloud.com/v2.0/tokens' | python -m json.tool | grep -A 7 token | awk '/id/ { print $2 }' | tr -d '"' | tr -d "," ) TOKEN=$(echo $AUTH | awk '{print $1}') ID=$(echo $AUTH | awk '{print $2}') curl -sH "X-Auth-Token: $TOKEN" -H "Content-type: application/json" -X DELETE https://$REGION.autoscale.api.rackspacecloud.com/v1.0/$ID/groups/$AS_GRP_ID/servers/$SERVER_UID?replace=true
Category Archives: Scripting
Scheduled unattended tasks – at
$ at time date $ at 11 am may 20 # at 02:00 AM Fri at> yum update glibc at> echo "Executing scheduled task" | logger at> shutdown -r +5 "Server is going to be rebooted in 5 minutes for scheduled task. Please save your work ASAP." at> <EOT> job 2 at 2015-02-06 02:00
Ends using CTRL+D that generates the <EOT> bit.
Source: http://www.computerhope.com/unix/uat.htm
Check the processes in the queue
atq
Check content of a job
at -c <job number>
Delete job
atrm <job number>
Also, you can cat/modify the job in /var/spool/cron/atjobs/ or /var/spool/at (in Centos)
If not installed, on Centos, make sure to start also ‘atd‘ service.
# chkconfig atd on && service atd start
WordPress PHP-FPM and Apache (with variables)
Sample setup for Apache virtual host and PHP-FPM pool with variables instead hard coded user details.
This could be handy if your are scripting your deploy (e.g. with Ansible).
In our example we are using the following:
Domain: example.com
SFTP user: example.com
Document root: /var/www/vhosts/example.com/httpdocs/
<VirtualHost *:80> ServerName example.com ServerAlias www.example.com DocumentRoot /var/www/vhosts/example.com/httpdocs <Directory /var/www/vhosts/example.com/httpdocs> require all granted Options Indexes AllowOverride All </Directory> ErrorLog "logs/example.com-error_log" CustomLog "logs/example.com-access_log" combined env=!forwarded CustomLog "logs/example.com-access_log" proxy env=forwarded # Configure proxy connector <Proxy "unix:/dev/shm/example.com-php5-fpm.sock|fcgi://php-fpm"> # we must declare a parameter in here (doesn't matter which) or it'll not register the proxy ahead of time ProxySet disablereuse=off </Proxy> # # Redirect to the proxy connector <FilesMatch \.php$> SetHandler proxy:fcgi://php-fpm </FilesMatch> <Directory /var/www/vhosts/example.com/httpdocs/wp-content/uploads> # Important for security, prevents someone from # uploading a malicious .htaccess AllowOverride None SetHandler none SetHandler default-handler Options -ExecCGI php_flag engine off RemoveHandler .cgi .php .php3 .php4 .php5 .phtml .pl .py .pyc .pyo <Files *> AllowOverride None SetHandler none SetHandler default-handler Options -ExecCGI php_flag engine off RemoveHandler .cgi .php .php3 .php4 .php5 .phtml .pl .py .pyc .pyo </Files> </Directory> </VirtualHost>
Create a file called example.com.conf in /etc/php-fpm/pool/
[example.com] listen = /dev/shm/$pool-php5-fpm.sock user = $pool group = $pool listen.owner = $pool listen.group = apache listen.mode = 0666 pm = dynamic pm.max_children = 35 pm.start_servers = 5 pm.min_spare_servers = 5 pm.max_spare_servers = 25 slowlog = /var/log/php-fpm/$pool-slow.log php_admin_value[error_log] = /var/log/php-fpm/$pool-error.log php_admin_flag[log_errors] = on php_value[session.save_handler] = files php_value[session.save_path] = /var/lib/php/session/$pool
BASH conditional expressions
-a file
True if file exists.
-b file
True if file exists and is a block special file.
-c file
True if file exists and is a character special file.
-d file
True if file exists and is a directory.
-e file
True if file exists.
-f file
True if file exists and is a regular file.
-g file
True if file exists and its set-group-id bit is set.
-h file
True if file exists and is a symbolic link.
-k file
True if file exists and its “sticky” bit is set.
-p file
True if file exists and is a named pipe (FIFO).
-r file
True if file exists and is readable.
-s file
True if file exists and has a size greater than zero.
-t fd
True if file descriptor fd is open and refers to a terminal.
-u file
True if file exists and its set-user-id bit is set.
-w file
True if file exists and is writable.
-x file
True if file exists and is executable.
-G file
True if file exists and is owned by the effective group id.
-L file
True if file exists and is a symbolic link.
-N file
True if file exists and has been modified since it was last read.
-O file
True if file exists and is owned by the effective user id.
-S file
True if file exists and is a socket.
file1 -ef file2
True if file1 and file2 refer to the same device and inode numbers.
file1 -nt file2
True if file1 is newer (according to modification date) than file2, or if file1 exists and file2 does not.
file1 -ot file2
True if file1 is older than file2, or if file2 exists and file1 does not.
-o optname
True if the shell option optname is enabled. The list of options appears in the description of the -o option to the set
builtin (see The Set Builtin).
-v varname
True if the shell variable varname is set (has been assigned a value).
-R varname
True if the shell variable varname is set and is a name reference.
-z string
True if the length of string is zero.
-n string
string
True if the length of string is non-zero.
string1 == string2
string1 = string2
True if the strings are equal. When used with the [[
command, this performs pattern matching as described above (see Conditional Constructs).
‘=’ should be used with the test
command for POSIX conformance.
string1 != string2
True if the strings are not equal.
string1 < string2
True if string1 sorts before string2 lexicographically.
string1 > string2
True if string1 sorts after string2 lexicographically.
arg1 OP arg2
OP
is one of ‘-eq’, ‘-ne’, ‘-lt’, ‘-le’, ‘-gt’, or ‘-ge’. These arithmetic binary operators return true if arg1 is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to arg2, respectively. Arg1 and arg2 may be positive or negative integers.
Source http://www.gnu.org/software/bash/manual/html_node/Bash-Conditional-Expressions.html
Dynamic MOTD on Debian
Here a simple script that setup a dynamic MOTD message ‘ubuntu-like’ on Debian servers:
#!/bin/bash # Script to install Dynamic MOTD on Debian servers # This version uses figlet if [[ $EUID -ne 0 ]]; then echo "This script must be run as root or using sudo" exit 1 fi if [ ! -f /etc/debian_version ] ; then echo "This script can run ONLY on Debian OS" exit 1 fi # Install required packages: # - figlet: ASCII art for hostname # - lsb-release: get distro details (fallback) apt-get install figlet lsb-release # Backup MOTD file mv -f /etc/motd{,.ORIG} # Symlink dynamic MOTD file ln -s /var/run/motd /etc/motd # Create dynamic motd environment mkdir /etc/update-motd.d/ cd /etc/update-motd.d/ cat <<'EOF' > 00-header #!/bin/sh # # 00-header - create the header of the MOTD # [ -r /etc/os-release ] && . /etc/os-release OS=$PRETTY_NAME if [ -z "$OS" ] && [ -x /usr/bin/lsb_release ]; then OS=$(lsb_release -s -d) fi figlet -f slant $(hostname) printf "\n" printf "\t- %s\n\t- OS version %s\n\t- Kernel %s\n" "$OS" "$(cat /etc/debian_version)" "$(uname -r)" printf "\n" EOF cat <<'EOF' > 10-sysinfo #!/bin/bash # # 10-sysinfo - generate the system information # date=`date` load=`cat /proc/loadavg | awk '{print $1}'` root_usage=`df -h / | awk '/\// {print $(NF-1)}'` home_usage=`df -h /home | awk '/\// {print $(NF-1)}'` memory_usage=`free -m | awk 'NR==2{printf "%.2f%%\n", $3*100/$2 }'` swap_usage=`free -m | awk '/Swap/ { printf("%3.1f%%", "exit !$2;$3/$2*100") }'` users=`users | wc -w` time=`uptime | grep -ohe 'up .*' | sed 's/,/\ hours/g' | awk '{ printf $2" "$3 }'` processes=`ps aux | wc -l` ip=`ifconfig $(route -n | grep '^0.0.0.0' | awk '{ print $8 }') | grep "inet addr" | awk -F: '{print $2}' | awk '{print $1}'` printf "System information as of %s\n\n" "$date" printf "IP Address:\t%s\tSystem uptime:\t%s\n" "$ip" "$time" printf "System load:\t%s\tProcesses:\t%s\n" "$load" "$processes" printf "RAM used:\t%s\tSwap used:\t%s\n" "$memory_usage" "$swap_usage" printf "Usage on /:\t%s\tUsage on /home:\t%s\n" "$root_usage" "$home_usage" printf "Local Users:\t%s\tProcesses:\t%s\n" "$users" "$processes" EOF cat <<'EOF' > 90-footer #!/bin/sh # # 90-footer - write the admin's footer to the MOTD # [ -f /etc/motd.tail ] && cat /etc/motd.tail || true EOF chmod +x /etc/update-motd.d/* clear echo "Installation completed. Please logout and login again to test."
If you are running CentOS7, here the how to for that OS.
BASH – File test operators
(From man bash)
The test command sorts using ASCII ordering.
-a file True if file exists. -b file True if file exists and is a block special file. -c file True if file exists and is a character special file. -d file True if file exists and is a directory. -e file True if file exists. -f file True if file exists and is a regular file. -g file True if file exists and is set-group-id. -h file True if file exists and is a symbolic link. -k file True if file exists and its ``sticky'' bit is set. -p file True if file exists and is a named pipe (FIFO). -r file True if file exists and is readable. -s file True if file exists and has a size greater than zero. -t fd True if file descriptor fd is open and refers to a terminal. -u file True if file exists and its set-user-id bit is set. -w file True if file exists and is writable. -x file True if file exists and is executable. -G file True if file exists and is owned by the effective group id. -L file True if file exists and is a symbolic link. -N file True if file exists and has been modified since it was last read. -O file True if file exists and is owned by the effective user id. -S file True if file exists and is a socket. file1 -ef file2 True if file1 and file2 refer to the same device and inode numbers. file1 -nt file2 True if file1 is newer (according to modification date) than file2, or if file1 exists and file2 does not. file1 -ot file2 True if file1 is older than file2, or if file2 exists and file1 does not.
Regex – Grep reference
Regex operator |
Meaning |
. |
Matches any single character. |
? |
The preceding item is optional and will be matched, at most, once. |
* |
The preceding item will be matched zero or more times. |
+ |
The preceding item will be matched one or more times. |
{N} |
The preceding item is matched exactly N times. |
{N,} |
The preceding item is matched N or more times. |
{N,M} |
The preceding item is matched at least N times, but not more than M times. |
– |
Represents the range if it’s not first or last in a list or the ending point of a range in a list. |
^ |
Matches the empty string at the beginning of a line; also represents the characters not in the range of a list. |
$ |
Matches the empty string at the end of a line. |
\b |
Matches the empty string at the edge of a word. |
\B |
Matches the empty string provided it’s not at the edge of a word. |
\< |
Match the empty string at the beginning of word. |
\> |
Match the empty string at the end of word. |
(a|b) |
Match a or b |
[abc] |
Range (a or b or c) |
[^abc] |
NOT a or b or c |
[a-z] |
Any letter (lowercase) from a to z |
[A-Z] |
Any letter (uppercase) from a to z |
[a-zA-Z] |
Any letter (upper and lowercase) from a to z |
[0-9] |
Any digit from 0 to 9 |
A most exhaustive cheat sheet is available here
Dynamic DNS update script
Below a script that I’ve created to update your Dynamic DNS service.
It has been tested on Raspian (Raspberry Pi), Ubuntu 18.04 and Debian 9.
It works with Internet.bs, No-ip.com and CloudFlare
https://bitbucket.org/thtieig/dynip_update/src/master/
Also, for who as a router running DD-WRT, here a quick article about how to set it up.
Enjoy! 😉
How to build a Debian package from source
There are plenty of articles on the net… but here I’m posting my notes about compiling netatalk.
First of all, you need the minimum packages:
apt-get install build-essential dh-make autotools-dev
I needed this on my Raspberry Pi for this article, and I didn’t want to make dirty the system using the common “make / make install
” commands.
This are the simple steps I’ve followed (all as root – even if it’s not the best practise).
mkdir /tmp/netatalk cd /tmp/netatalk wget http://downloads.sourceforge.net/project/netatalk/netatalk/3.1.7/netatalk-3.1.7.tar.gz tar xzvf netatalk-3.1.7.tar.gz cd netatalk-3.1.7
Make sure the folder has this format:
<name_of_the_package>-<version>
ALL in lowercase!
dh_make -e [email protected] -f ../netatalk-3.1.7.tar.gz
It will ask for the type of the package. To make things easier, just select single entering s.
Edit the file debian/control
adding the missing bits (example below):
Source: netatalk Section: net Priority: extra Maintainer: root <[email protected]> Build-Depends: debhelper (>= 8.0.0), autotools-dev Standards-Version: 3.9.3 Homepage: http://netatalk.sourceforge.net/ #Vcs-Git: git://git.debian.org/collab-maint/netatalk.git #Vcs-Browser: http://git.debian.org/?p=collab-maint/netatalk.git;a=summary Package: netatalk Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: AppleTalk user binaries Open Source AFP fileserver capable of serving many Macintosh clients simultaneously as an AppleShare file server (AFP)
Then, add debian/rules
adding this line, to pass custom configure parameters:
override_dh_auto_configure: dh_auto_configure -- --with-init-style=debian-sysv --with-zeroconf
The <TAB> is what you have to press to indent the code. Without that TAB, the file won’t work properly. Before dh_auto_configure there is a TAB 🙂
MAKE SURE that the syntax gets highlighted like this:
I’ve read that it should be good to run
dpkg-depcheck -d ./configure
before the next step.
Honestly, I didn’t do that because it requires an extra package calleddevscripts
that installs loads of dependencies, which I didn’t want to add on my Raspberry pi.
In a different situation, I would probably have done that.
Then run:
dpkg-buildpackage -us -uc
…and wait.
If you get something like this…
dpkg-deb: building package `netatalk' in `../netatalk_3.1.7-1_armhf.deb'. dpkg-genchanges >../netatalk_3.1.7-1_armhf.changes dpkg-genchanges: including full source code in upload dpkg-source --after-build netatalk-3.1.7 dpkg-buildpackage: full upload (original source is included)
…you’ve been lucky! And you can cd ..
and you should have your package .deb
created and ready to be installed with a simple dpkg -i .deb
Good luck! 🙂
NOTE: I’ve noticed that the compile might fail due to ‘acl‘ package missing. I’m not a master in compiling, so what I’ve done is the following
apt-get install acl
Than I’ve modified include/atalk/acl.h
start at line 63, adding #define O_IGNORE 0
to make it look like following:
#define O_NETATALK_ACL 0 #define O_IGNORE 0 #define chmod_acl chmod
This trick was from here
Than, you need to commit the change with the following command: dpkg-source --commit
and save adding a little description like “patch to compile with no ACLs” or something like that.
This made me possible to finish the building of the package and have the deb.
UPDATE: Debian jessy systemd
# Packages to install
apt-get install build-essential libevent-dev libssl-dev libgcrypt11-dev libkrb5-dev libpam0g-dev libwrap0-dev libdb-dev libtdb-dev libmysqlclient-dev avahi-daemon libavahi-client-dev libacl1-dev libldap2-dev libcrack2-dev systemtap-sdt-dev libdbus-1-dev libdbus-glib-1-dev libglib2.0-dev tracker libtracker-sparql-1.0-dev libtracker-miner-1.0-dev autotools-dev debhelper
# How to edit debian/rules
override_dh_auto_configure: dh_auto_configure -- --with-init-style=debian-systemd --without-libevent --without-tdb --with-cracklib --enable-krbV-uam --with-pam-confdir=/etc/pam.d --with-dbus-sysconf-dir=/etc/dbus-1/system.d --with-tracker-pkgconfig-version=1.0
And here the already compiled file netatalk_3.1.8
Backup Raspberry Pi SD on your Mac… and restore.
Plug the SD in your Mac.
In the Terminal, as root, use diskutil to identify your SD.
Generally it’s the last in the list, if you’ve just plugged in.
root:~ # diskutil list
You will see something like this:
In my case, the SD is /dev/disk4
. For this reason, I run the following to unmount the whole disk.
root:~ # diskutil umountDisk /dev/disk4 Unmount of all volumes on disk4 was successful
Once done, you can create the backup using dd utility, but make sure to change the device from /dev/diskX
to /dev/rdiskX
, adding the “r“.
root:~ # dd if=/dev/<span style="color: #ff0000;">rdisk4</span> of=/path/to/mypibackup.img bs=1m
To restore, of course… invert if (input file) with of (output file)… 🙂
root:~ # dd if=/path/to/mypibackup.img of=/dev/rdisk4 bs=1m