Hello all. I have need two traps on the same command. I have the trap on control-c working. I tried control-z, it didn’t work. One trap exits the script. The other trap continues to the next loop (next drive). The code for the loop through all mswin drives is complex. So, this is a simplified version what I need to do.
scanvirus_cancel_trap='false'
scanvirus_skip_trap='false'
control_c()
# run if user hits control-c
{
scanvirus_cancel_trap='true'
}
# trap keyboard interrupt (control-c)
trap control_c SIGINT
clamscan -r /
if scanvirus_cancel_trap = 'true' ];then
printf 'exiting...'
exit
fi
if scanvirus_skip_trap = 'true' ];then
printf 'skip to next drive...'
continue
fi
I tried control-z in script. It didn’t work. All online sources said it wouldn’t work. What other signal/key will stop clamscan and allow me to trap it?
A possible alternative to what you’re now doing is to write individual functions (ie individual apps) so that your overall app is modularized, then write a “master script” that runs individual functions in some order.
The idea is that if, for instance based on what you appear to be trying to do, you do a standard “CTL-C” killing the process during a print function, your master script would continue to the next function.
Along this line of thought of architecting your application in a modern, “modular” way you might consider
Some languages are better suited to providing the individual functionality and the glue
If you adopt a language, you will often find “fremeworks” for that language which will provide organization and structure, and enhance re-usability of code.
At least in the beginning, you may find that using an IDE can greatly get you up to speed. Although some frameworks have some kind of quickstart default setup, an IDE will not only provide that but also a visual tool. Some IDE will even autocomplete for you, reducing typos and other mistakes while also doing easy library lookups.
Another benefit of using a proper language is that there will in almost all cases be useful tools to verify the integrity of your code, easily compile or run, test, minimize, obfuscate, and lots, lots more. Some tools will handle all the workflow in your app, or the workflow of creating your app. In other words, today’s Developer has choices to use tools that even manages and co-ordinates other tools.
If you do settle on a language, you might check whether a Meetup or other User Group for that topic exists in your area, it’s a good place to not only learn and understand quickly, who knows you might find a partner for your project.
Control-c exits the scanvirus script. In the scan ‘-w’ command, it will scan all mswin drives. Control-c stops clamscan, umounts the drives, and exits the script.
Now, I need control-(key) to skip to the next drive. Stop clamscan and skip to the next drive. I’d show the code, but i’m still fixing other sections of the code.
I figured out how to do it with only control-c. I’d like to try with two control-keys instead.
Language? You mean bash script? It’s already modular, functions to do tasks.
Am referring to various coding languages commonly used which may start with but of course does not end with
javascript, python, perl, ruby, java, c+, c#, …
Efficient coding is based on the idea of re-usable blocks of code that requires minimal testing, structure and centralized configuration (and plenty more principles). Re-inventing the wheel is to be avoided, if there are common ways things are done, that is not something to be avoided.
I very experienced in programing, the older languages: ADA,PASCAL, ASSEMBLY(6502), ATARI 8-BIT(MAC65, ACTION!). The modern is: ‘C’. I’m expanding to bash script. All the general programing skills i’v mastered(structured programing, debugging, data structures, pointer variables, etc). Recursion: still don’t understand. It’s only the specific command usage for tasks I need to learn. Also, I have limited time to work on it. Back to the task:
Can you do one than trap for different tasks? I have control-c to cancel out and unmount the drive. I need a trap key to cancel the “clamscan” task and move to next drive. I have to go back and fix other unrelated code before I post it. Thanks.
It would if commands started by your shell ignored SIGTSTP. Of course it means you won’t be able to suspend your script, but you won’t be able to do it anyway if you will redefine SIGTSTP handler.
Your description suggests to me that currently you are executing all scans of your drives as one task,
And,
The problem you want to overcome suggests to me that you should instead create scan tasks for each drive individually, and load them into a master script where if the task to scan any drive is killed(not the entire scanning), then your master script would proceed to the next task which contains scanning the next drive.
If there is any kind of limitation to this approach, it’s that your tasks are loaded and must run sequentially(I have not seen this restriction when coding in modern languages).
Note also that if your individual scans were defined or run separately, each could also contain their own scoped methods for things like unique options and even killing the task.
Also, even though you are coding in BASH, it might help to apply some modern concepts like MVC (Model-View-Controller) which separates your code into completely separate code that provides the UI, data, and the functional code the UI touches to interact with the data.
It uses ‘blkid’ to show all drives, reads the data, and scan drives. The script code improves on clamscan command, adding multi-drive logging later, mswin only. It has only one dependency, ‘clamscan’, it’s engine. It’s a self-contained script, no libraries needed and standard linux commands. At the end of the code, posted a last release.
If there is any kind of limitation to this approach, it’s that your tasks are loaded and must run sequentially(I have not seen this restriction when coding in modern languages).
Note also that if your individual scans were defined or run separately, each could also contain their own scoped methods for things like unique options and even killing the task.
Control-c stops the ‘clamscan’ command, unmounts the drive, and exits the script. Lets the user cancel it. Control-(key) skips to the next drive. Other option, I can add a read key to choose ‘cancel or skip drive?’. The UI can always use improvement.
Parallel processing? I’m trying to make the code as simple as possible. Also, I’m going to disable suspend and other trap signals, still figuring that out.
Also, even though you are coding in BASH, it might help to apply some modern concepts like MVC (Model-View-Controller) which separates your code into completely separate code that provides the UI, data, and the functional code the UI touches to interact with the data.
I’m still trying to master BASH. Parallel process coding isn’t part of my skill set, not that it isn’t something I want to learn later. Two, it meant to be a self-contained script, no libraries, simple to use, and standard linux commands. You can copy it off my post, paste it into a file, make it executable, and your ready to run. My instructions need some work. The new version makes dated directory, stores viruses found there, and put the log of all drives scanned.
The above is the reason I made it. Simple to use, scanvirus does all the work. No install, No libraries, just run on the superuser command line. This version is out of date. I’v fixed most of the usage problems and added a better logging system, better than clamscan does. Not to brag. I’m doing system recovery now. So, it will be a while before I come back to it.
#!/bin/bash
#: Title : scanvirus
#: Date Created: Thu Sep 2 19:27:00 PST 2010
#: Last Edit : Tue Feb 23 2:30:00 PST 2016
#: Author : Lord Valarian #: Version : 2.0.0 beta2
#: Description : virus scanning application, clamscan engine
#<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-nd/4.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/">Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License</a>.
#Software License: http://creativecommons.org/licenses/by-nc-nd/4.0/
#modified for personal use only, no modified uploads permitted, non-commercial use only
#Open bin folder
#Place this file inside "/home/bin/"
#
#Right-click on scanvirus
#Click on properties
#Click on permissions
#Check executable and click ok
#install clamav or run setup
#Click Control -> Tools -> Open Terminal
#Enter termal command: scanvirus --setup
#Enter admin password, wait for it to finish. Don't close terminal.
#kdeicon disabled
#Enter terminal command: scanvirus --kdeicons
#close terminal windows
#
#Click on either desktop icon to scan
#Warning! only use control-c to exit
Create_KDE_linux_scan_icon() {
cat > ScanVirus_KDE_Linux_Scan.desktop <<EOF
#!/usr/bin/env xdg-open
[Desktop Entry]
Comment[en_US]=
Comment=
Exec=sh scanvirus -linux
GenericName[en_US]=
GenericName=
Icon=kde
MimeType=
Name[en_US]=ScanVirus - linux anti-virus scan
Name=ScanVirus - linux anti-virus scan
Path=$PATH
StartupNotify=true
Terminal=true
TerminalOptions=\s--noclose
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=
X-KDE-SubstituteUID=false
X-KDE-Username=
X-SuSE-translate=trueEOF
EOF
#set file permissions
chmod 744 ScanVirus_KDE_Linux_Scan.desktop
}
Create_KDE_windows_scan_icon() {
cat > ScanVirus_KDE_Windows_Scan.desktop <<EOF
#!/usr/bin/env xdg-open
[Desktop Entry]
Comment[en_US]=
Comment=
Exec=sh scanvirus -mswin
GenericName[en_US]=
GenericName=
Icon=kde
MimeType=
Name[en_US]=ScanVirus - windows anti-virus scan
Name=ScanVirus - windows anti-virus scan
Path=$PATH
StartupNotify=true
Terminal=true
TerminalOptions=\s--noclose
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=
X-KDE-SubstituteUID=false
X-KDE-Username=
X-SuSE-translate=true
EOF
#set file permissions
chmod 744 ScanVirus_KDE_Windows_Scan.desktop
}
Virus_Vault_Directory_Check()
{
#create tmp directory if not present
if -d "/tmp" ]; then
printf "root/tmp/ directory present
"
else
printf "creating tmp directory
"
mkdir tmp
#chmod 744
fi
#create virus Vault if not present
if -d "/tmp/VirusVault" ]; then
printf "root/tmp/virusvault/ present
"
else
printf "creating virus vault
"
mkdir /tmp/VirusVault
chmod 744 /tmp/VirusVault
fi
}
Scan_Results_Filter()
{
Line=''
IFS=''
delete_line_flag=true
scan_results_flag=false
while read -r -N 1 c; do
if "$delete_line_flag" = 'true' ]; then
Line=''
echo -en "\E[2K\r"
delete_line_flag=false
fi
#if not newline character
if [[ "$c" != $'
' ]] ; then
printf "%s" $c
Line+=${c}
#printf "(%s)
" $Line
if "$c" = ':' ];then
Line=''
fi
#if new line
else
if "$Line" = '----------- SCAN SUMMARY -----------' ]; then
scan_results_flag=true
fi
if "$scan_results_flag" = 'true' ]; then
printf "
"
Line=''
elif "$Line" == *"FOUND"* ]] || "$Line" == *"moved to"* ]];then
printf "
"
Line=''
else
delete_line_flag=true
fi
fi
done
unset IFS
}
#read -p "Done. Press any key..." -n1 -s;printf "";
#####################
# shortcut code for clamscan #
#####################
control_c()
# run if user hits control-c
{
printf 'Exiting...
'
scanvirus_trap_flag='true'
#kill clamscan
}
#export TERM=vt100
#trap keyboard interrupt (control-c)
scanvirus_trap_flag='false'
trap control_c 2
#commands
if "$1" = "-mswin" ] || "$1" = "-w" ]; then
Virus_Vault_Directory_Check;
freshclam
printf "
.....scanvirus mswin.....
"
#blkid -o list
scanvirus_flag="false"
while read -ra line; do
if "$scanvirus_flag" = 'false' ]; then
scanvirus_flag="true"
read -ra line
read -ra line
#break
fi
Device_Label=${line[0]}
File_System=${line[1]}
Drive_Label=${line[2]}
Mount_Point=${line[3]}
#if file system vfat or ntfs
if $File_System = 'ntfs' ] || $File_System = 'vfat' ]; then
#printf "%s %s %s %s
" ${line[0]} ${line[1]} ${line[2]} ${line[3]}
printf "__________________________________________________
"
#if device not mounted
if $Mount_Point = '(not' ]; then
#udisksctl mount -b $devicename -o ro
Device_Mounted_Flag=true
while read -ra command_output; do
printf "%s %s %s %s
" ${command_output[0]} ${command_output[1]} ${command_output[2]} ${command_output[3]%.}
break
done < <(udisksctl mount -b "$Device_Label")
command_output_mount=${command_output[0]}
if "$command_output_mount" = 'Mounted' ]; then
printf "%s mounted
" $Drive_Label
else
printf "Error: mount %s
" $Drive_Label
fi
command_output_scandir=${command_output[3]%.}
#elif "${line[3]}" = '(in' ]; then
# printf "(in use)
"
else
Device_Mounted_Flag=false
command_output_scandir=$Mount_Point
fi
#scan only or move files
if "$2" = "-m" ] || "$2" = "-movetovault" ]; then
printf "Move to Virus Vault: /tmp/VirusVault/
"
Movefile_Parm="--move=/tmp/VirusVault"
else
Movefile_Parm=''
printf "Scan only
"
#printf "
"
fi
printf "
scanning: %s %s
" $Drive_Label $command_output_scandir
clamscan -r $command_output_scandir $Movefile_Parm --follow-dir-symlinks=0 --follow-file-symlinks=0 | Scan_Results_Filter
#if drive mounted, unmount it
if "$Device_Mounted_Flag" = 'true' ];then
while read -ra command_output; do
break
done < <(udisksctl unmount -b "$Device_Label")
command_output_unmount=${command_output[0]}
if "$command_output_unmount" = 'Unmounted' ]; then
printf "%s unmounted
" $Drive_Label
else
printf "Error: unmount %s
" $Drive_Label
fi
fi
printf "__________________________________________________
"
fi
#break
if "$scanvirus_trap_flag" = 'true' ]; then
break
fi
done < <(blkid -o list)
#virus vault files read only
chmod 744 /tmp/VirusVault
elif "$1" = "-linux" ] || "$1" = "-l" ]; then
printf ".....Scanning linux.....
";
freshclam
printf "
"
clamscan -r / --exclude-dir=/sys --exclude-dir=/proc --exclude-dir=/dev --exclude-dir=/.snapshots --follow-dir-symlinks=0 --follow-file-symlinks=0 | Scan_Results_Filter
elif "$1" = "-help" ] || "$1" = "-h" ]; then
printf "
Scan Virus
help commands
-------------
virus scan linux files
p1: -l or -linux
virus scan windows files
p1: -w or -mswin
p2: -m or -movetovault (optional)
--setup: setup scanvirus
--kdeicons: setup icons
"
elif "$1" = "--setup" ]; then
printf "
"
printf "ScanVirus Setup...
"
su -c "zypper --non-interactive install clamav;chkconfig freshclam on;freshclam;exit"
printf "
"
elif "$1" = "--kdeicons" ]; then
#Create_KDE_linux_scan_icon;
#Create_KDE_windows_scan_icon;
#printf "KDE Icons Created
";
printf "Disabled
";
else
printf "
Scan Virus
help commands
-------------
virus scan linux files
p1: -l or -linux
virus scan windows files
p1: -w or -mswin
p2: -m or -movetovault (optional)
--setup: setup scanvirus
--kdeicons: setup icons
"
fi
exit 0
# End Of Script
No parallel processing.
But, might be described as “hierarchical processing” since only one task is actively running at a time. “Worker” tasks are managed and run by a “master task.”
Specific to your question, each Worker task should include its own code for exception handling so that when something like a CTL-C is invoked, only that Worker task will receive the input and act accordingly.
Is typical of modern coding, the idea that a single, enormous piece of code is not the right approach.
My main linux drive is in use for file recovery. However, I now have a linux flash drive to use for now to test the script (file recovery output drive).
As to having a file as list of drives to be scanned(drives.conf), I tried it and it was impractical. I like the simplicity of scanvirus, just a minimum number of commands to remember (1 command and 1 command + option). It does all the work of finding drives/partitions, scanning each, creating folders for drives as their scanned, moving found viruses to the folder, and writing a practical log to the folder.
Using control-(key) to skip drives, it not to practical for someone in a hurry and can’t stay in the room. A simple drive mask command would be a better, a positive or negative mask. Coding more than one mask will be hard, but not impossible. You would need to use ‘blkid -o list’ to find a search parm. I could include a short cut command, ‘scanvirus -p-d]’ list drives/partitions’. The drive label or device name that can be searched for the mask(blkid -o list).
scanvirus -w -pm mask1] -nm mask1]
This would filter out(negative/in(positive) any drives with masks.
Scanvirus: A ‘Simplified Command Line User Interface’(SCLUI) using ‘clamscan’ as it’s engine.
Make text file ‘scanvirus’. Copy code and paste to ‘scanvirus’. Set execute flag on scanvirus. Enter terminal superuser mode. Enter ‘scanvirus --help’. Your ready.
FYI, I’m going to add the ability to scan linux format flash drives, a better system than now. I’m going to use the same method as mswin scan. I’m currently rebuilding it, putting new features back in, structured logging and virus storage. A few more commands, still keeping it a very limit set of commands. Finally created a name for i’m doing.