Showing posts with label bash. Show all posts
Showing posts with label bash. Show all posts

Monday, April 1, 2019

Sha-Bang Your Scripts

Sometimes, Windows can be a friendly scripting environment. You write a batch file, and you run it. You write a Powershell script, and provided your Execution Policy allows it, you run it. If it is a batch file, you can even double-click it in the GUI. Powershell, however, you either need to run in its shell, or wrap it in a batch script. The bash shell works a bit differently.

The Sha-Bang (Sharp Bang) declares to the shell what is needed to execute the script. A bash script (example.sh) would normally look like:

#!/bin/sh
echo "Hello, World!"


You would then add the executable flag:

chmod +x example.sh

The same can be done with other interpreters, such as python or perl:

#!/usr/bin/env python
print("Hello, World!")


Or:

#!/usr/bin/perl -w
print "Hello, World!\n"


The same can be done with Powershell on linux, provided your shell knows where Powershell lives.

$ which powershell
/snap/bin/powershell


If you get a response, then Powershell is in your env PATH, so you can have:

#!/usr/bin/env powershell
Write-Host "Hello, World!"


Powershell users in Windows will note that just as running a local script, you need a dot-slash:

$ ./example.ps1
Hello, World!

Friday, November 9, 2018

BASH: Assign Output of Command to a Variable

In Powershell it is pretty easy to assign output to a variable, but not being a BASH scripter I needed to look up how to do it there. I found a good article at CyberCiti.

The goal was to create a cron job to update one of my Raspberry Pi systems. As I am a packager I like to create logs, so I want to create a log with the date and time of the update job. To automate this, I needed to get the date from the system and parse it. I also want to see when ClamAV's definitions were last updated. So I have two instances where I turn command output into a string variable:

#!/bin/bash
LOG=$(date +/home/david/logs/%Y%m%d_at_%H%M.log)
touch $LOG
BAR="--------------------------------------------------"
echo $BAR >> $LOG
sudo apt-get update >> $LOG
echo $BAR >> $LOG
sudo apt-get upgrade -y >> $LOG
echo $BAR >> $LOG
sudo apt-get dist-upgrade -y >> $LOG
echo $BAR >> $LOG
sudo apt-get autoremove -y >> $LOG
echo $BAR >> $LOG
echo Last /var/log/clamav/freshclam.log >> $LOG
CLAM=$(tail -n 1 /var/log/clamav/freshclam.log)
DATE="${CLAM:0:24}"
echo "${DATE}" >> $LOG

My Log then looks like this (I shortened it a bit here) with above examples highlighted:

david@rpi3b ~/bin $ cat ~/logs/20181109_at_0923.log 
--------------------------------------------------
Hit:1 http://archive.canonical.com/ubuntu xenial InRelease
[...]
Hit:17 https://deb.etcher.io stable Release
Reading package lists...
--------------------------------------------------
Reading package lists...
Building dependency tree...
Reading state information...
Calculating upgrade...
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
--------------------------------------------------
Reading package lists...
Building dependency tree...
Reading state information...
Calculating upgrade...
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
--------------------------------------------------
Reading package lists...
Building dependency tree...
Reading state information...
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
--------------------------------------------------
Last /var/log/clamav/freshclam.log
Fri Nov  9 08:26:33 2018

Another nifty page from CyberCiti details the below technique:

The last trick there was to get just the timestamp from the ClamAV log. The log in it's raw form looks like:

Fri Nov  9 08:26:33 2018 -> --------------------------------------

I could leave that as it is (it is just a log, after all), but getting a substring is what the boss would want if this was for her, so I parse it out. The desired string is 24 characters long, so we get the string and parse it:

CLAM=$(tail -n 1 /var/log/clamav/freshclam.log)

Then create a masked version with substring expansion in a new variable from $CLAM and character position 0 and with a length of 24 (so, characters 0:23):

DATE="${CLAM:0:24}"

Then echo that into my log:

echo "${DATE}" >> $LOG

Monday, November 5, 2018

Working with Your Command Line History

A trick I always forget is utilizing command line history, aside from just up-arrow.

Powershell:

This is all from "How To Geek: How to Use Your Command History in Windows PowerShell", which is a very useful site.

I spend a lot of time in Powershell, but also in PS Sessions with other systems. The up-arrow method is not always great when entering/returning from a PS Session, as it will iterate through all recent commands on your native and remote sessions. Get-History will, however, stick to the current session.
PS A:\> Clear-History
PS A:\> Get-History

  Id CommandLine
  -- -----------
 109 Clear-History

PS A:\> Enter-PSSession remotesystem
[remotesystem]: PS C:\Users\johndoe\Documents> Get-History
[remotesystem]: PS C:\Users\johndoe\Documents> cd C:\Temp\
[remotesystem]: PS C:\Temp> Get-History

  Id CommandLine
  -- -----------
   1 Get-History
   2 cd C:\Temp\

[remotesystem]: PS C:\Temp> exit
PS A:\> Get-History

  Id CommandLine
  -- -----------
 109 Clear-History
 110 Get-History
 111 Enter-PSSession remotesystem

In order to use my history (were it lengthy) I would call Invoke-History -Id n. Let's say I wanted to clear my history:
PS A:\> Invoke-History -Id 109
Clear-History
PS A:\> Get-History

  Id CommandLine
  -- -----------
 113 Clear-History

There is other great info at the linked article.

BASH:

BASH is a bit simpler, and maintains history better than Powershell. A good reference is at ss64.com, an invaluable site for the command line. Their article on BASH history is at: Connamd Line History.

The basics are easy. To see your history, use the history command. It will display the commands and their id number:
$ history
    1  history
    2  cd ~
    3  history
    4  touch somefile.txt
    5  history
    6  cd /c/temp
    7  history

To execute history item 4, simply enter !4 and return. If your history is lengthy, you could use [ctrl]+r and then start typing the command you want to find. This will begin to autocomplete the command with the appropriate text. If you want to find the command's id in your history, pipe history through grep.
$ history | grep -i some
    4  touch somefile.txt
    9  touch somefile.txt
   10  history | grep -i some