What happened to OC? - CLOSED Carnage?!
Solaris

Bash Scripting - Mount CD/DVD [User Friendly]

12 posts in this topic

I am making a script template for installing updates from files off of a CD/DVD and replacing the files within the target directory. In order, here's what I want it to do. It's kind of a rough draft at the moment with some pseudo-code. First and foremost, it will check to see if the script is being run as root. If not, it will exit. I just want some opinions and help on making this script better (still a WIP).

 

  • 1. Detect the running state of the service about to be updated and stop it. If the exit status is 0, it will move to the next segment of the script. If it refuses to stop, it will proceed to kill the service via PID.
  • 2. Check the status of the install media. It will first force a mount for as a precautionary measure and then check the status in /proc. If the exit status isn't 0, something went wrong and it will report that the user needs to check the installation media. If it's successful, it will continue onto the next segment of the script. I would also like it to not make a big deal about what the disc is named in /media. For example, my RHEL 6 disk auto-mounts to /media/RHEL-6.8\ Server.x86_64/, but I would like to to kind of read like /media/*. No other media should be mounted in this directory at the same time since the only READ/WRITE capability to offload and onload onto the system is via the CD/DVD drive. Just incase, as a safety measure, wanted some thoughts on a better way to implement this.
  • 3. Verify the correct files are on the install media. Using something like GREP and using its results to determine if it's correct or not. If the files are there, I would somehow like to implement an md5sum (somehow create a temp pipe to a text file to print the names of the files, locations and hashes) check against both the files in the install directory and on the install media to determine if they are the same thing. If they are not, it will proceed to remove the old files and copy the new ones from the installation media to the target directory.
  • 4. Secondary check to verify that the files are installed in the target directory and match the md5sum against what it reported from the installation media. Just incase something goes wrong. If the md5sum doesn't match the earlier hash, it will remove the effected files and copy the appropriate one to the directory. It will loop until its' exit status is successful and move to the next segment of the script.
  • 5. Unmount and eject the installation media. Will move to next segment of the script with 0 exit status.
  • 6. Finally, restart the service and run the application with parameters. I would like the script to exit, but not kill the process/services it just ran.

 

This way it makes it easier for our maintainers out in the field to install these updates. Some of the filenames and paths have been redacted.

 

#!/bin/bash
# Check if running as root. Prevents running as standard user.
    FILE="/tmp/out.$$"
        GREP="/bin/grep"
    #....
# Make sure only root can run our script
    if [[ $EUID -ne 0 ]]; then
            echo "This script must be run as root. Run 'su -' and then execute" 1>&2
        exit 1
    fi
# ...
#############################################################################
# Check to see if Anti-Virus is running. Stop service if it is.
            echo "Checking to see if service is running..."
SERVICE=[insertservicehere] # Haven't quite figured out if I want PID or by name.
    if ps ax | grep -v grep | grep $SERVICE > /dev/null
        then
            echo "$SERVICE service running, killing it."
    else
            echo "$SERVICE is not running, proceeding with install."

            # For logging purposes
            echo "$SERVICE is not running, proceeding with Application Updates" | mail -s "$SERVICE down" root
    fi
#############################################################################
# Variables for mounting CD/DVD

MOUNT=/dev/sr0 /media/*

#############################################################################
# Check for CD-ROM Mount
            echo "Looking for Update media..."
    if grep -qs "$MOUNT" /proc/mounts; then
                echo "CD-ROM is mounted!"
        else
                echo "CD-ROM is not mounted!"
            mount "$MOUNT"
        if [ $? -eq 0 ]; then
                echo "Mount Successful!"
        else
                echo "Something went wrong with the mount... Please check your media"; then
        exit
        fi
    fi

#############################################################################
# Filename Variables
1=file1
2=file2
3=file3

#############################################################################
# Verify the designated files are on the disc
    if grep -qs "[$1]" /media/discname/file1; then
            echo "[$1] located."
        else
            echo "[$1] is not found."
    fi

    if grep -qs "[$2]" /media/discname/file2; then
            echo "[$2] located."
        else
            echo "[$2] is not found."
    fi

    if grep -qs "[$3]" /media/discname/file3; then
            echo "[$3] located."
        else
            echo "[$3] is not found."
    fi

#############################################################################
# Copy the the files to the /usr/local/application
        echo "Removing old Update Files..."
    rm /usr/local/application/[$1]
    rm /usr/local/application/[$2]
    rm /usr/local/application/[$3]
        echo "Removed!"
        echo "Copying new signatures to /usr/local/application"
    cp -r /mnt/[$1] /usr/local/application
    cp -r /mnt/[$2] /usr/local/application
    cp -r /mnt/[$3] /usr/local/application
        echo "Finished copying new updates!"

#############################################################################
# Check if files were copied into /usr/local/application
    if grep -qs "[$1]" /mnt; then
            echo "[$1] was installed."
        else
            echo "[$1] is not found."; then
    fi

    if grep -qs "[$2]" /mnt; then
            echo "[$2] was installed."
        else
            echo "[$2] is not found."
    fi

    if grep -qs "[$3]" /mnt; then
            echo "[$3] was installed."
        else
            echo "[$3] is not found."
    fi

#############################################################################
# Start Anti-Virus service and Start Scan

something something something
#############################################################################
# Unmount and Eject /dev/sr0

umount /media/*

eject -t /dev/sr0

exit
Edited by iTails
WaeV likes this

System Administrator (Well Rounded) | AWS | Azure | Microsoft 365

Share this post


Link to post
Share on other sites

Tiddy-bits:

9 minutes ago, WaeV said:

Looks like a decent start to me.

 

RHEL = systemd, right? Or is this an older version? :huh: "Service" doesn't always mean the same thing, depending on the environment bash is running in.

RHEL = Red Hat Enterprise Linux. RHEL doesn't implement systemd due to compatibility and stability purposes, since systemd is still technically new and not a Red Hat accredited init system. I'm lucky that RHEL 6 even includes the 2.6.32 kernel (rolling release kernel is around 4.x?).

 

SERVICE=[variable_here] is just the name of the service running on the system, but I think it's probably going to be harder to target a name of a service than a PID. Could probably just use the appropriate 'start' and 'stop' commands used with systemctl.


System Administrator (Well Rounded) | AWS | Azure | Microsoft 365

Share this post


Link to post
Share on other sites
5 minutes ago, iTails said:

since systemd is still technically new and not a Red Hat accredited init system

Lol, it's their project that they've managed to export to nearly every Linux distro. They developed it in Fedora and it caught on. Not being enterprise-ready yet makes sense though.

 

From systemd's Wikipedia page:

Quote

Lennart Poettering and Kay Sievers, the software engineers working for Red Hat who initially developed systemd

 

(I'm kinda salty because I really don't like systemd but it's completely taken over. I seek refuge in the BSDs)

Share this post


Link to post
Share on other sites
41 minutes ago, WaeV said:

Lol, it's their project that they've managed to export to nearly every Linux distro. They developed it in Fedora and it caught on. Not being enterprise-ready yet makes sense though.

 

From systemd's Wikipedia page:

 

(I'm kinda salty because I really don't like systemd but it's completely taken over. I seek refuge in the BSDs)

Yeah, it's pretty unfortunate because there was nothing really broken with sysvinit in the past releases of RHEL, other than it being a little slower. The only major difference I've noticed, at least with the 4.x kernels is that it allows for the capability of doing kernel updates and changing other settings that would normally require a system restart in sysvinit where systemd and capture the running state of the system, restart the kernel in the background with the appropriate changes and you can keep moving on. On the downside of that, applications HAVE to, as in are pretty much forced, to hook into systemd if they want any chance of their services or processes to be able to keep running during that state. It's way too much reliance on systemd and it's a central point of failure in the event something goes terribly wrong, but I don't think it will be a huge issue once people start taking a huge notice to ZFS or btrfs, because by default it creates a snapshot of the current running state of the system before the update and you'll be able to log back into single user mode on the last snapshot to roll back the changes if necessary. On a desktop it makes sense, but on a server... that's way too much of a risk, especially if you're running mission critical resources, but most organizations have a redundant server they bring online to put the one needing to be updated into maintenance mode.

 

On another note, this was a pretty good read over the advantages and disadvantages of traditional init systems vs systemd.

Edited by iTails
WaeV likes this

System Administrator (Well Rounded) | AWS | Azure | Microsoft 365

Share this post


Link to post
Share on other sites

Update: Here's where I have gotten with this script. A lot more than what I started off with. Still a lot I want to do with it and now I kind of want to re-write it now that I've learned how to use zenity... Not sure how well this code is going to display with this editor, so be weary of that. Still have a lot of cleaning up to do on this script and I'm constantly finding more ways to do things in this script that isn't going through hoops to do something.

 

 

echo #############################################################################
echo # 1. Check if running as root. Prevents running as standard user.                                                                #
echo #############################################################################
# Make sure only root can run our script
    if [[ $EUID -ne 0 ]]; then
            echo ' '
            echo -e "\e[1m \e[41m ($TIME):This script must be run as root. Run 'su -' and then execute \e[49m" 1>&2
            echo ' '
        exit 1
    fi
echo #############################################################################
echo # 2. Script-wide variables                                                  #
echo #############################################################################
TIME=$(date -u +%c%M) # Prints Time
SERVICE=#### # PID of program
MOUNT='/dev/sr0 /disc)' # Mount point for the disc
RESULT=$? # Return status of last command.

echo #############################################################################
echo # 3. Check to see if Anti-Virus is running. Stop service if it is.          #
echo #############################################################################
            echo -e "\e[49m ($TIME): Checking to see if service is running..."
    if ps ax | grep -v grep | grep $SERVICE > /dev/null # Search PID in ps
        then
            echo -e "($TIME):\e[1m \e[41m PID $SERVICE (uvscan) service running, killing it. \e[49m"
            pkill $SERVICE # Kill the service
    else
            echo "($TIME): PID $SERVICE (program) is not running, proceeding with Updates"
            echo "($TIME): PID $SERVICE (program) is not running, proceeding withUpdates" | mail -s "PROGRAM PID# $SERVICE Down For Updates!" root
    fi

echo #############################################################################
echo # 4. Check for CD-ROM Mount                                                 #
echo #############################################################################
                echo "($TIME):Looking for Update media..."
    if grep --color -qs "$MOUNT" /proc/mounts; then # Search /proc/mounts for the mount point of the disc
                echo -e "($TIME):\e[1m \e[42m CD-ROM is mounted! \e[49m"
        else
                echo "($TIME): \e[1m \e[41m CD-ROM is not mounted!\e[49m"
            mount /dev/sr0 /disc # Mount the disc at /disc
    fi
        if [ $? -eq 0 ] ; then
                echo -e "($TIME): \e[1m \e[42m Mount Successful!\e[49m"
        else
                echo -e "($TIME): \e[1m \e[41m Something went wrong with the mount... Please check your media \e[49m"
        fi

sleep 1

 

echo #############################################################################
echo # 5. Verify the designated files are on the disc                            #
echo #############################################################################
    if grep --color -r 'file1.dat /disc; then # Search and print results for the file 'file1.dat' on the disc
            echo -e "($TIME): \e[1m \e[42m file1.dat located. \e[49m"
        else
            echo -e "($TIME): \e[1m \e[41m file1.dat is not found. \e[49m"
    fi

sleep 1

 

    if grep --color -r 'file2.dat' /disc; then # Search and print results for the file 'file2.dat' on the disc
            echo -e "($TIME): \e[1m \e[42m file2.dat located. \e[49m"
        else
            echo -e "($TIME): \e[1m \e[41m file2.dat is not found. \e[49m"
    fi

sleep 1

 

    if grep --color -r 'file3.dat' /disc; then # Search and print results for the file 'file3.dat' on the disc
            echo -e "($TIME): \e[1m \e[42m file3.dat located. \e[49m"
        else
            echo -e "($TIME): \e[1m \e[41m file3.dat is not found. \e[49m"
    fi

sleep 1

 

echo #############################################################################
echo # 6. Copy the the files to the /usr/local/uvscan                            #
echo #############################################################################


        echo -e "($TIME): \e[49m Removing old Updates..."

        echo -e "($TIME): \e[49m Removing file1"
    rm /path/to/file1.dat > /dev/null # Remove 'file1.dat' from /path/to/file1.dat directory
            if [ $RESULT -eq 0 ]; then
        echo -e "($TIME): \e[1m \e[42m file1.dat was removed successfully. \e[49m"
    else
        echo -e "($TIME): \e[1m \e[41m file1.dat was not found. Assuming clean install. \e[49m"
    fi

sleep 1

 

        echo "($TIME): Removing file2.dat"
    rm /path/to/file2.dat > /dev/null # Remove 'file2.dat' from /path/to/file2.dat directory
            if [ $RESULT -eq 0 ]; then
        echo -e "($TIME): \e[1m \e[42m file2.dat was removed successfully. \e[49m"
else
        echo -e "($TIME): \e[1m \e[41m file2.dat was not found. Assuming clean install. \e[49m"
    fi

sleep 1

 

        echo "($TIME): Removing file3.dat"
    rm /path/to/file3.dat > /dev/null # Remove 'file3.dat' from /path/to/file3.dat directory
            if [ $RESULT -eq 0 ]; then
        echo -e "($TIME): \e[1m \e[42m file3.dat was removed successfully. \e[49m"
else
        echo -e "($TIME): \e[1m \e[41m file3.dat was not found. Assuming clean install. \e[49m"
    fi

sleep 1

 

    cp /disc/file1.dat /path/to/folder && if grep --color -r 'file1.dat' /path/to/folder; then # Copy files from /disc to /path/to/folder
        echo -e "($TIME): \e[1m \e[42m  file1.dat was installed into /path/to/folder. \e[49m"
            else
        echo -e "($TIME): \e[1m \e[41m file1.dat was NOT installed into /path/to/folder! \e[49m"
    fi

 

    cp /disc/file2.dat /path/to/folder && if grep --color -r 'file2.dat' /path/to/folder; then # Copy files from /disc to /path/to/folder
        echo -e "($TIME): \e[1m \e[42m  file2.dat was installed into /path/to/folder. \e[49m"
            else
        echo -e "($TIME): \e[1m \e[41m file2.dat was NOT installed into /path/to/folder! \e[49m"
    fi

sleep 1

 

    cp /disc/file3.dat /path/to/folder && if grep --color -r 'file3.dat' /path/to/folder; then # Copy files from /disc to /path/to/folder
        echo -e "($TIME): \e[1m \e[42m file3.dat was installed into /path/to/folder \e[49m"
            else
        echo -e "($TIME): \e[1m \e[41m file3.dat was NOT installed into /path/to/folder! \e[49m"
    fi

sleep 1

 

echo #############################################################################
echo # 7. Unmount and Eject /dev/sr0                                             #
echo #############################################################################
            echo "($TIME): Unmounting and Ejecting the Disc! Please remove disc from the tray!"
    umount /disc # Unmount the disc from /disc
    eject -t /dev/sr0 # Eject the disc from the drive.
            echo -e "($TIME):\e[1m \e[42m Update completed! If you received errors, check your installation media or refer to the administration guide. \e[49m"

done

Edited by iTails

System Administrator (Well Rounded) | AWS | Azure | Microsoft 365

Share this post


Link to post
Share on other sites

Edit: I just made my life 10x easier by hooking my script into a package called 'dialog'. All you really need to know is the exit status of the last command with 'dialog' and you put it in your script with something like the following:

 


echo "#############################################################################
# Script-Wide Variables                                                     #
#############################################################################"
RESULT=$?

echo "#############################################################################
# Initial Message                                                           #
#############################################################################"
dialog --title 'Mount CD/DVD' --msgbox "Welcome to the CD/DVD Mounter. Press OK to Continue." 20 30

echo "#############################################################################
# Mount Media YES/NO Prompt                                                 #
#############################################################################"

if [ $RESULT  -eq 0 ]; then
    dialog --yesno "Do you want to mount the disc and view its contents?" 20 30
        if [ $RESULT -eq 0 ]; then
            mkdir /disc
            mount /dev/sr0 /disc | exec nautilus /disc | exec nautilus /home/$USER | dialog --title 'Mount Complete' --msgbox "Mount Completed!" | exit 0
    else
        if [ $RESULT -eq 1 ]; then
            exit 1
        fi
    fi
fi

I9kwe.png


System Administrator (Well Rounded) | AWS | Azure | Microsoft 365

Share this post


Link to post
Share on other sites
17 hours ago, WaeV said:

That's awesome. Can you get input from the user?

Yeah, each option in the --yesno parameter has an exit status of either 0 or 1. 0 being yes and 1 being no, so you carry that into your script with the $RESULT function ($? reads the exit status of last command) and you can use if/then/else statements for the rest of the script. There's a ton of other stuff 'dialog' can do that Zenity can't.

 

But there's some awesome stuff you can do with it like file selection and whatnot as well.

 

f0yr4.png

 

 

cdialog (ComeOn Dialog!) version 1.3-20160209
Copyright 2000-2015,2016 Thomas E. Dickey
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

* Display dialog boxes from shell scripts *

Usage: dialog <options> { --and-widget <options> }
where options are "common" options, followed by "box" options

Special options:
  [--create-rc "file"]
Common options:
  [--ascii-lines] [--aspect <ratio>] [--backtitle <backtitle>] [--beep]
  [--beep-after] [--begin <y> <x>] [--cancel-label <str>] [--clear]
  [--colors] [--column-separator <str>] [--cr-wrap] [--date-format <str>]
  [--default-button <str>] [--default-item <str>] [--defaultno]
  [--exit-label <str>] [--extra-button] [--extra-label <str>]
  [--help-button] [--help-label <str>] [--help-status] [--help-tags]
  [--hfile <str>] [--hline <str>] [--ignore] [--input-fd <fd>]
  [--insecure] [--item-help] [--keep-tite] [--keep-window] [--last-key]
  [--max-input <n>] [--no-cancel] [--no-collapse] [--no-cr-wrap]
  [--no-items] [--no-kill] [--no-label <str>] [--no-lines] [--no-mouse]
  [--no-nl-expand] [--no-ok] [--no-shadow] [--no-tags] [--nook]
  [--ok-label <str>] [--output-fd <fd>] [--output-separator <str>]
  [--print-maxsize] [--print-size] [--print-version] [--quoted]
  [--scrollbar] [--separate-output] [--separate-widget <str>] [--shadow]
  [--single-quoted] [--size-err] [--sleep <secs>] [--stderr] [--stdout]
  [--tab-correct] [--tab-len <n>] [--time-format <str>] [--timeout <secs>]
  [--title <title>] [--trace <file>] [--trim] [--version] [--visit-items]
  [--week-start <str>] [--yes-label <str>]
Box options:
  --buildlist    <text> <height> <width> <tag1> <item1> <status1>...
  --calendar     <text> <height> <width> <day> <month> <year>
  --checklist    <text> <height> <width> <list height> <tag1> <item1> <status1>...
  --dselect      <directory> <height> <width>
  --editbox      <file> <height> <width>
  --form         <text> <height> <width> <form height> <label1> <l_y1> <l_x1> <item1> <i_y1> <i_x1> <flen1> <ilen1>...
  --fselect      <filepath> <height> <width>
  --gauge        <text> <height> <width> [<percent>]
  --infobox      <text> <height> <width>
  --inputbox     <text> <height> <width> [<init>]
  --inputmenu    <text> <height> <width> <menu height> <tag1> <item1>...
  --menu         <text> <height> <width> <menu height> <tag1> <item1>...
  --mixedform    <text> <height> <width> <form height> <label1> <l_y1> <l_x1> <item1> <i_y1> <i_x1> <flen1> <ilen1> <itype>...
  --mixedgauge   <text> <height> <width> <percent> <tag1> <item1>...
  --msgbox       <text> <height> <width>
  --passwordbox  <text> <height> <width> [<init>]
  --passwordform <text> <height> <width> <form height> <label1> <l_y1> <l_x1> <item1> <i_y1> <i_x1> <flen1> <ilen1>...
  --pause        <text> <height> <width> <seconds>
  --prgbox       <text> <command> <height> <width>
  --programbox   <text> <height> <width>
  --progressbox  <text> <height> <width>
  --radiolist    <text> <height> <width> <list height> <tag1> <item1> <status1>...
  --rangebox     <text> <height> <width> <min-value> <max-value> <default-value>
  --tailbox      <file> <height> <width>
  --tailboxbg    <file> <height> <width>
  --textbox      <file> <height> <width>
  --timebox      <text> <height> <width> <hour> <minute> <second>
  --treeview     <text> <height> <width> <list-height> <tag1> <item1> <status1> <depth1>...
  --yesno        <text> <height> <width>

Auto-size with height and width = 0. Maximize with height and width = -1.
Global-auto-size if also menu_height/list_height = 0. 

 

 

Update: Taking some code examples to try to create a robust control panel for all of the scripts, so all you have to do is select the operation you want to execute and it will run automatically. Also learning how to use the 'trap' command is very helpful, because I learned that you can't assign or depend on process IDs in Unix/Linux because they get recycled and you will end up either killing an innocent process or SIGTERM will wait until that PID is available to kill it. So I found out that you need something that will constantly update a temporary file with the current PID of a process to be able to kill it should the need arise for it. For example, I wanted to do something like "Are you done yet?" and if you pressed "Yes" it would kill that PID listed in the table (in the temporary file) and finish running the remainder of the script, so that there are no rouge processes running afterwards for process management. 

 

Example: https://bash.cyberciti.biz/guide/A_menu_box

 

 


#!/bin/bash # utilitymenu.sh - A sample shell script to display menus on screen # Store menu options selected by the user INPUT=/tmp/menu.sh.$$ # Storage file for displaying cal and date command output OUTPUT=/tmp/output.sh.$$ # get text editor or fall back to vi_editor vi_editor=${EDITOR-vi} # trap and delete temp files trap "rm $OUTPUT; rm $INPUT; exit" SIGHUP SIGINT SIGTERM # # Purpose - display output using msgbox # $1 -> set msgbox height # $2 -> set msgbox width # $3 -> set msgbox title # function display_output(){ local h=${1-10} # box height default 10 local w=${2-41} # box width default 41 local t=${3-Output} # box title dialog --backtitle "Linux Shell Script Tutorial" --title "${t}" --clear --msgbox "$(<$OUTPUT)" ${h} ${w} } # # Purpose - display current system date & time # function show_date(){ echo "Today is $(date) @ $(hostname -f)." >$OUTPUT display_output 6 60 "Date and Time" } # # Purpose - display a calendar # function show_calendar(){ cal >$OUTPUT display_output 13 25 "Calendar" } # # set infinite loop # while true do ### display main menu ### dialog --clear --help-button --backtitle "Linux Shell Script Tutorial" \ --title "[ M A I N - M E N U ]" \ --menu "You can use the UP/DOWN arrow keys, the first \n\ letter of the choice as a hot key, or the \n\ number keys 1-9 to choose an option.\n\ Choose the TASK" 15 50 4 \ Date/time "Displays date and time" \ Calendar "Displays a calendar" \ Editor "Start a text editor" \ Exit "Exit to the shell" 2>"${INPUT}" menuitem=$(<"${INPUT}") # make decsion case $menuitem in Date/time) show_date;; Calendar) show_calendar;; Editor) $vi_editor;; Exit) echo "Bye"; break;; esac done # if temp files found, delete em [ -f $OUTPUT ] && rm $OUTPUT [ -f $INPUT ] && rm $INPUT

 

 

Utilitymenu.sh-output-1.png

Edited by iTails
WaeV likes this

System Administrator (Well Rounded) | AWS | Azure | Microsoft 365

Share this post


Link to post
Share on other sites

Update on this. Project was scrapped due to the dialog package not being approved for use. I'm just sticking with basic menus that call on other scripts.

 

http://stackoverflow.com/questions/20224862/bash-script-always-show-menu-after-loop-execution

 

The other scripts are easy and just automates mounting/unmounting of discs. However, there is no intuitive "guide" on mounting blank CDs/DVDs in Linux. Once a disc is inserted, the OS will convert it to UDF, but on our systems we have automatic UDF format conversion disabled by default to prevent offloading from unauthorized persons. Trying to find some hack-around way of getting this crap to work.

Edited by Solaris

System Administrator (Well Rounded) | AWS | Azure | Microsoft 365

Share this post


Link to post
Share on other sites
  • Recently Browsing   0 members

    No registered users viewing this page.