Showing posts with label script. Show all posts
Showing posts with label script. Show all posts

Monday, 6 April 2020

bash scripting reminders of basics

Problem:

I want quick reminders for bash shell scripting because I don't write bash scripts often enough to memorize everything.

Notes:

The following reminders assume you're already familiar with the basics of bash shell scripting and simply need a reminder of more commonly used syntax, etc. These reminders are for myself but I hope you also find them useful.

Reminder shortcuts

As the number of reminders grow I hope this index will help you find what you need. (It certainly helps me.)



Reminders:

Top of script starts with #!/bin/bash

#!/bin/bash
See this tldp.org reference page for details.

Simple variables

Examples of simple variables

NAME="Delta"
echo "Hello $NAME!"

Concatenate strings


HELLO="Hello, "
NAME="Lily"

echo $HELLO$NAME
# output: Hello, Lily

HELLO="Hello, "
NAME="Alex"
GREET="${HELLO}${NAME}!"

echo "$GREET"
#output: Hello, Alex!


GREET="Hello, "
GREET+="Ninja"

echo "$GREET"
#output: Hello, Ninja

String quotes of bash scripting

DIRECTION="Right"
echo "Turn $DIRECTION"  # => Turn Right
echo 'Turn $DIRECTION'  # => Turn $DIRECTION

Bash for-loop


VAR=""
for NAME in 'alpha' 'bravo' 'charlie' 'delta'; do
  VAR+="${NAME} "
done

echo $VAR
# output: alpha bravo charlie delta 

Bash if-and, bash if-or

if [ $FILENAME == 'important.txt' ] && [ -f $FILENAME ]; then
  echo "this is an important file"
fi
if [ $NAME == 'Hector' ] || [ $NAME == 'Miguel' ]; then
  echo "this person is on a hero's journey"
fi

Bash check if directory exists

DIR="/usr/mydir/"

if [ -d "$DIR" ]; then
  echo "directory exists"
else
  echo "directory not found"
  exit 1
fi
DIR="/usr/mydir/"

[ "$DIR" == "" ] && { echo "directory string is empty"; exit 1; }
[ -d "${DIR}" ] && echo "directory exists" || echo "directory not found"

Bash if directory does not exist


DIR="/usr/mydir/"

if ! [ -d "$DIR" ]; then
  echo "directory does not exist"
else
  echo "directory exists"
fi

Bash check if file exists

if [ -f "/opt/myfile.txt" ]; then
  echo "file found"
else
  echo "file not found
fi

For items in bash array

DIR3="/opt/mydir3"
DIRTOCHECK=("/opt/mydir1" "/opt/mydir2" $DIR3)

for dir in "${DIRTOCHECK[@]}"
do
  if [ -d "${dir}" ]; then
    echo "found directory ${dir}"
  else
    echo "did not find directory ${dir}"
  fi
done

Command line arguments in bash scripting

# example: yourscript.sh arg1 2nd-arg

echo "All arguments values:" $@
# output: All arguments values: arg1 2nd-arg

echo "First argument:" ${1}
# output: First argument: arg1

echo "Second argument:" ${2}
# output: Second argument: 2nd-arg

echo "Total arguments:" $#
# output: Total arguments: 2

For more detailed information, please refer to this tecadmin.net tutorial

How to check if git repo needs update from remote upstream with bash scripting

This how-to assumes you already have a git repository installed, a remote upstream setup, and have navigated into the local repository via your script.

git fetch
if [ $(git rev-parse HEAD) == $(git rev-parse @{u}) ]; then
  # add logic for when no update is needed, e.g.
  echo 'already up to date.'
else
  # add logic for when update is needed, e.g.
  echo 'updating to latest.'
  git pull
fi

How to check if script is on correct git branch for bash script

The following example assumes master branch is desired and the script has already navigated to the local repository.

if ! [ $(git rev-parse --abbrev-ref HEAD) == "master" ]; then
  echo "NOT in master branch."
else
  echo "in master branch."
fi

Why these reminders?

This page is intended to remind myself quickly without requiring too much reading. I hope it's helped you out, too.

References:

Tuesday, 7 January 2014

Disable Mac start-up chime in OS X 10.9 Mavericks ("Band-Aid" workaround only, for now)

Problem:

I would like to disable the start-up chime my OS X Mavericks-based Mac makes so that restarting the computer will not be so loud.

Notes:

  • The solutions below were tested on OS X 10.9 Mavericks and may work on other versions, but there is no guarantee.
  • This how-to was written as a reminder for myself in case this needs to be replicated or undone later. It is not a full solution and still a bit advanced for the average OS X user to follow, which makes it unacceptable to post as a "solution" (in my opinion).
  • You're welcomed to follow the solutions below, but use the more permanent one at your own risk.

Solution 1 (temporary):

Turn the volume of your computer down before shutdown or restart. The start-up chime should match your system's volume.

Note that muting seems to have mixed reported results in forums and other online posts, where some systems will chime at the same volume as the system volume, even when muted (resulting in lots of surprise chimes), yet others report that muting works.

Solution 2 (advanced workaround, but a bit more permanent):

This solution goes through the steps to write a script that turns the system volume to 0, and rigs it to run upon the user selecting to shutdown or restart the machine via the apple menu.

Warnings:

  • Make sure you are comfortable with Terminal, shell scripts, file permissions, and reading manual pages (if you get stuck). If you are not comfortable using Terminal (or are prone to making typos), you should probably not try this. Attempt at your own risk.
  • Every time you start up OS X, the volume will be set to 0 (which may not be a bad thing if you're already trying to avoid surprises by turning the chime sound off to begin with)

This is a modification of the solution found here, but modified in a way that should work on more OS X setups. The modified steps are posted below as a reminder in case the link ever goes down.

Steps:

  1. Run the Terminal app with an administrator account
  2. Create a script for muting (replacing "/path/to/" with a valid path -- if you're not sure what this means, do not proceed with the rest of the steps)
    sudo nano /path/to/volume-off.sh
    
  3. Write the volume-off script (or copy and paste the following into it):
    #!/bin/bash
    
    osascript -e "set Volume 0"
    
  4. Make file executable with following command (replacing "/path/to/" with where the script is saved):
    sudo chmod u+x /path/to/volume-off.sh
    
  5. Check that we can hook this to the OS X logout (see if any hooks exist - only one or none can exist, not more). In Terminal, use the command:
    sudo defaults read com.apple.loginwindow LogoutHook
    

    You should end up with something similar to "The domain/default pair of (com.apple.loginwindow, LogoutHook) does not exist".

  6. Add hook to run script at logout, replacing "/path/to/" with where the script is saved:
    sudo defaults write com.apple.loginwindow LogoutHook /path/to/volume-off.sh
    

To Undo Solution 2:

  1. Check that the logout hook exists in Terminal with the following command:
    sudo defaults read com.apple.loginwindow LogoutHook
    

    You should end up with something similar to "/path/to/volume-off.sh" with "/path/to/" being where your script is saved.

  2. Delete the logout hook in Terminal with the following command:
    sudo defaults delete com.apple.loginwindow LogoutHook
    

Notes on solution 2:

  • Just like in the original solution, the volume-off.sh script is also saved in /Library/Scripts/
  • Make sure the permissions of the script is set so that only the owner can write to the file, since the script is run as sudo (and would be an obvious security risk if it can be re-written by just anyone).
  • The script must be owned by root.
  • Again, this will turn the volume to 0 upon logout rather than simply mute. This is because many people online seem to report mixed success with muting.
  • The commands for setting both a login and a logout hook, as well as removing them are as follows:
    • sudo defaults write com.apple.loginwindow LoginHook /path/to/your-login-script.sh
    • sudo defaults write com.apple.loginwindow LogoutHook /path/to/your-logout-script.sh
    • sudo defaults delete com.apple.loginwindow LoginHook
    • sudo defaults delete com.apple.loginwindow LogoutHook
  • The commands for checking if a hook exists for login or logout are as follows:
    • sudo defaults read com.apple.loginwindow LoginHook
    • sudo defaults read com.apple.loginwindow LogoutHook

Very brief discussion on problems with other solutions found online:

The following will only make sense to anyone who has Googled how to disable the start-up Mac chime and read through the various proposed solutions. It briefly outlines why these workarounds weren't posted here. You can skip this section if you'd like.

nvram SystemAudioVolume method:

  1. too dangerous for most users (you can easily accidentally turn your computer into an expensive paperweight with the nvram command)
  2. many mixed results and uninformed posts online on why that solution used to work (read: everyone seems to be guessing. If you don't want to be one of those guessers, you can read up on nvram in the slightly out-of-date book "Mac OS X for Unix Geeks (Leopard)" in Google Books as that section appears to be viewable for free, at least as of January 2014)
  3. the solution doesn't work on all OS X and Mac combinations
  4. the solution does NOT work in Mavericks (tested) as the system will change the SystemAudioVolume value automatically

rc startup/shutdown script method:

  1. does not work in Mavericks as start-up has been moved to launchd instead (see Apple developer documentation on Launch Daemons and Agents
  2. any daemon-supporting mechanism may change in future versions of OS X, making this solution possibly unreliable (and worse, it will leave potentially unwanted files dangling deep within the system)
  3. this solution is way too complicated to post for the average user

existing software:

  1. many don't work on all versions of OS X (mixed results reported in forums, etc.)
  2. all software Googled do not describe exactly what system-wide changes are being made, making it hard to determine how permanent they are, as well as how well do they handle OS upgrades
  3. Mavericks seems to have broken a lot of the existing software, so it's hard to recommend a good one

the solution 2 in this blog post:

  1. it's not possible to do if you are not the system administrator
  2. it's not possible to do if you or your system administrator has already hooked something to com.apple.loginwindow LogoutHook
  3. it's possible that it won't work if you shut down your computer using a different mechanism than the usual Apple UI ways
  4. it's still inaccessible to most users
  5. if permissions are not set correctly, you could potentially create a security hole

an official Apple "turn off start-up sound" preferences item:

  1. does not exist/was eliminated
  2. if you're from Apple, perhaps you could help out with this? =)

References:

Thursday, 14 November 2013

Autorun startup script on Raspberry Pi Arch Linux

Problem:

I want to run a custom script when my Raspberry Pi running Arch Linux starts up. I only need the most basic instructions.

Pre-requisites:

  • You're comfortable running commands in the console
  • You know what to do if you accidentally brick your RPi
  • You know how to write shell scripts
  • You're already familiar with basic linux shell commands

Disclaimer:

These instructions were written as a reminder to myself for a fresh install of Arch Linux (2013-07-22 version) in order to run custom startup scripts. Please read through the instructions and make sure you understand all the steps first before attempting this. Results may vary, but because you're doing things as root, you might brick your RPi if you do something wrong (or if things change in different versions of Arch Linux). Follow at your own risk.

Feel free to let me know of any typos in the comments and I'll fix them right away. Best of luck!

Solution:

Note that this is only one solution out of many possible ones. It may not even be the accepted correct practice, but it happened to work after lots of Googling. You can modify the instructions if you feel comfortable doing so. Also note that these instructions were written as a reminder for myself in case I need to do this again, so they may be a bit brief. This solution was tested to work with the archlinux-hf-2013-07-22.img.zip image from the Raspberry Pi downloads page. Your results may vary with other versions (including this not working at all).

Assumptions:

  • startup script is located at: /scripts/my_startup_script.sh
  • script already has executable privileges for root
  • we want to run our script in multi-user runlevel (if this doesn't make sense, see here for details)

Step 1: create the startup service file for systemd

In this example we're making a file called "myauto.service". In practise you can name it whatever you want, so long as it doesn't replicate another service's name.

# nano /etc/systemd/system/myauto.service

Step 2: edit the .service file to contain the information needed to both run and install your service

In this example, we've included some bare-basics only which points to our startup script /scripts/my_startup_script.sh:

[Unit]
Description=Autostart custom script

[Install]
WantedBy=multi-user.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/scripts/my_startup_script.sh

Once you've edited this above file as you'd like, save it.

This file says that we want to make a service referred to as myauto.service, which should be installed at the runlevel of multi-user, that runs a one-shot command which is our startup script.

Step 3: install the service

Here we get systemctl to install the service. Remember to replace "myauto" with the name of your .service file created earlier.

# systemctl enable myauto.service

You'll see a symbolic link created in /etc/systemd/system/multi-user.target.wants that corresponds to the .service file created earlier (in this case myauto.service).

Step 4: check if service is running (after restart)

You can check if the service is running by the following command (substituting your service's name for myauto.service below):

# systemctl is-enabled myauto.service

Step 5: where do I get more information?

Check out the very helpful systemd documentation at https://wiki.archlinux.org/index.php/Systemd

Sunday, 13 May 2012

Copy files in order using Linux or OS X

Problem:

How do I copy files in sorted order using the Linux or OS X Terminal?

Solution:

In the terminal, you can use a combination of the "find", "sort", "xargs", and "cp" commands to copy files in sorted order.

For instance, first switch to the directory that has the files you would like to copy:

cd /path/to/media/directory

Then copy the files in sorted order:

find . -print0 | sort -z | xargs -0 cp --parents
  --target-directory=/path/to/destination -v

Note that the above command is a single line, (but it appears split into two in order to fit into this page.)

In the cp command, the -v flag will help you see if files are being copied in the desired order. This can be omitted if you do not wish to monitor the files being copied. To customize the order of your sort, simply customize the flags used with the 'sort' command (see the manual pages for 'sort' using the command 'man sort', if you're unsure of how to do this).

Why copying files in sorted order can be useful:

Some MP3 players, digital media players, and other devices play back media in the order that files were copied to it. With some file managers, files can be copied out of order, in reverse-sorted order, or in other ways that copy files out of the order that is desired (such as copying multiple files in parallel). There are also other situations where copying files in a particular sorted order would be useful. For instance, copying files in some required order to a custom-built robot's flash memory, etc.

Other thoughts:

Although the command 'cp -R' can also recursively copy things in order, the method mentioned above in this post should give a bit more flexibility customizing the sorted order of the copied files.

Thursday, 15 March 2012

Bash shell script confirmation prompt

To prompt for user confirmation before performing a dangerous action in a bash shell script, you can use the following code:

read -p "Confirm (y/n)? " -n 1 -r
if [[ $REPLY =~ ^[Yy]$ ]]
then
  # get cursor on next line (optional)
  echo
  # do dangerous stuff here
fi

Friday, 2 March 2012

gedit something in OS X terminal

Trying out OS X after using Ubuntu, I often found myself typing into the terminal "gedit <something>" to do a quick edit of a file, which didn't work out of the box. If you're here and you also didn't want to give up that old habit, here's one way to get that terminal command to work again. (I got this to work with gedit 3.2.6 under OS X 10.7.3, so your mileage might vary with other setups...)

1) install the gedit app
(This can be found at their project page: http://projects.gnome.org/gedit/

Caution: if you don't know what "sudo" is, how to write shell scripts, or what file permissions are, read up on it before doing the next few steps or you could potentially screw up your system.
 
2) create a shell script named 'gedit' in a folder defined in your PATH (in my case, I just put it in /usr/bin), and have it open a file using gedit

In the terminal, create a new shell script named 'gedit' using a text editor. In this example we use the 'nano' text editor.

sudo nano /usr/bin/gedit

Type in the following script:
#!/bin/bash

open -a /Applications/gedit.app/Contents/MacOS/gedit $1


Save.


This lets you do simple "gedit something.txt" or "gedit" commands from the terminal. You can change this script as you desire for more complicated behavior.


3) make the script executable
sudo chmod +x /usr/bin/gedit


To test if this worked out, open up a file using gedit in the terminal, e.g. "gedit myfavoritefile.txt"


4) how to undo this
To undo all of this, simply delete the /usr/bin/gedit script you created and uninstall gedit.