Technical Review: Practical Automation with PowerShell

It’s becoming increasingly difficult to find a standout book on PowerShell in today’s crowded market. I’m sure everyone is familiar with such books as:

  • “Learn PowerShell in a Month of Lunches” (best for newbies)
  • “Learn PowerShell Scripting in a Month Lunches” (best for learners).
  • “Windows PowerShell in Action” (best handbook)

Let’s assume you have read the first two and are trying to find the next one to completely master PowerShell skills, get more practice, and gain insights. Allow me to introduce “Practical Automation with PowerShell” by Matthew Dowst.

Surprisingly to me, this book became my favorite (despite having read several bestsellers, some of which are mentioned above), and I thoroughly enjoyed both reading and reviewing it. The main reason is its comprehensive table of contents, which addresses everything one encounters on a daily basis: automation of clouds, on-premise servers, databases, and other essential tasks.

Click to see TOC
  • 1. POWERSHELL AUTOMATION
  • 2. GET STARTED AUTOMATING
  • 3. SCHEDULING AUTOMATION SCRIPTS
  • 4. HANDLING SENSITIVE DATA
  • 5. POWERSHELL REMOTE EXECUTION
  • 6. MAKING ADAPTABLE AUTOMATIONS
  • 7. WORKING WITH SQL
  • 8. CLOUD-BASED AUTOMATION
  • 9. WORKING OUTSIDE OF POWERSHELL
  • 10. AUTOMATION CODING BEST PRACTICES
  • 11. END-USER SCRIPTS AND FORMS
  • 12. SHARING SCRIPTS AMONG A TEAM
  • 13. TESTING YOUR SCRIPTS
  • 14. MAINTAINING YOUR CODE
  • APPENDIX A: DEVELOPMENT ENVIRONMENT SET UP

The book teaches you how to design, write, test and maintain your scripts. If you work as a part of team – this book is also for you: “Handling sensitive data” and “Sharing scripts among a team” chapters are awesome and extremely helpful. Additionally, it covers integration with Jenkins, Azure Automation and Azure Functions. Consequently, after reading the book, you will be able to execute automations in mixed environments with different sets of services.

I highly recommend this book to anyone passionate about PowerShell. However, if you’re just starting out, I suggest beginning with “month of lunches” books before diving into this one to refine your skills and develop an automation engineer’s mindset.

Kudos to the author for an excellent work!

Simple PostgreSQL Backup Agent

Learn how to backup PostgreSQL data

Dockerized cron job to backup PostgreSQL database or multiple databases on different hosts. It’s based on Alpine docker image, so the image size is less than 11 Mb. The script can be also used without docker and docker compose or as a base for your own dockerized cron jobs. My general recommendation is to run docker container on your backup host to provide a kind of isolation from the management partition.

The script or “agent” does the following:

  • Reads content of /config/passfile to get pg_dump connection parameters
  • Verifies if the backup can be done by executing a dry run for each db
  • If the dry run is completed and plain format set, produces plain-text sql script and compresses it with gzip
  • If the dry run succeeds and custom format set, outputs a custom backup archive (more flexible and by default)
  • Cleans up the storage folder. Files older than 30 days are deleted
  • Redirects all cron job statuses to stdout
  • Keeps backup files under ./psql/backups/{hostname}/{dbname}/ on your host
  • Default settings: twice a day at 8:30 and 20:30 UTC; custom format; clean backups older than 30 days

Current limitations:

  • no encryption for specific databases (in to-do list)
  • no handling of wildcars in passfile (in to-do list)

Content

  • Dockerfile – describes docker image
  • docker-compose.yml – docker compose file to build and run agent service
  • /config/cronfile – cron job schedule settings
  • /config/passfile – PostgreSQL .pgpass actually
  • /config/psql_backup.sh – the script itself

Usage guide

  • check out the passfile and provide your own connection parameters
  • verify the cron job settings in the /config/cronfile
  • change make_backup function argument to set format output (plain/custom)
  • update cleaner function argument at the bottom of the script if necessary
  • edit dockerfile/docker-compose.yml or script itself if necessary
  • run docker compose build
  • run docker compose up -d
  • check out the stoud of the container to get the job’s status
  • TO RESTORE: use psql (if plain set) or pg_restore command (if custom format set)

Dockerfile

FROM alpine:3.16.2
LABEL AUTHOR="Roman Levchenko"
LABEL WEBSITE="rlevchenko.com"
RUN mkdir /etc/periodic/custom \
    && mkdir -p /backup/config \ 
    && touch /var/log/cron.log \
    && apk --no-cache add \
    postgresql14-client=14.5-r0 \
    bash=5.1.16-r2
COPY /config/cronfile /etc/crontabs/root
COPY /config/psql_backup.sh /etc/periodic/custom/backup
COPY ["/config/psql_backup.sh","/config/passfile","/backup/config/"]
RUN chmod 755 /etc/periodic/custom/backup \
    && chmod 0600 /backup/config/passfile
CMD ["-f","-l","8", "-L", "/dev/stdout"]
ENTRYPOINT ["crond"]

Script (excerpt)

# Clean old backup files
function cleaner()
{
set -o pipefail -e
	if [[ -n $(find $BACKUP_DIR \( -name "*.sql.gz" -o -name "*.custom" \) -type f -mtime +"$1") ]]; 
	then
		echo -e "\n${GREEN}[INFO]${OFF} ${BOLD}There are backup files older than $1 days. Cleaning up the following files:${OFF}"
		find $BACKUP_DIR \(-name "*.sql.gz" -o -name "*.custom" \) -print -type f -mtime +"$1" -exec rm {} \;
	else 
		echo -e "\n${GREEN}[INFO]${OFF} ${BOLD}There are no backup files older than $1 days. \nHave a nice day!${OFF}"
	fi
set +o pipefail +e
}

Result

Sample Output (w/error and success messages):