I have a multiple choice menu script to display top file system disk usage. It is working script but I have problem with one of the file system naming /data.
DATA_RAW_DISK_DUMP="/tmp/$(basename $0).$$.disk_raw_data"
DATA_RAW_FILE_LIST="/tmp/$(basename $0).$$.file_raw_data"
MY_WORKING_DIR=$(pwd)
MY_OUTPUT_FILE="MY_WORKING_DIR/$(basename $0).output"
#check existing output file
if [[ -e $MY_OUTPUT_FILE ]] ; then
if [[ -e ${MY_OUTPUT_FILE}.old ]] ; then
rm ${MY_OUTPUT_FILE}.old
fi
mv $MY_OUTPUT_FILE ${MY_OUTPUT_FILE}.old
fi
#will prompt for choices - ignore any arguments
echo "Please select from below:" cat<<EOF
1. /data
2. /data01
3. DO_ALL_DATA_AT_ONCE
Press ENTER to exit EOF
echo -n "Selection:"
read ans
if [[ $ans == "" ]] ; then
echo "Bye"
exit 0
fi
case $ans in
"1"|"2"|"3")
FS_TARGET="$ans"
;;
*)
echo "Unknown option - quitting"
echo "Bye"
exit 0
;;
esac
DATA="/data0${FS_TARGET}/*"
if [[ $FS_TARGET -eq 3 ]] ; then
#if the selection is 3, then we just do everything, in one go
DATA="/data/* /data01/*"
fi
#do the du first
echo "Running du for ${DATA}, this will take a while, please wait..." >&2
du -sk ${DATA} > $DATA_RAW_DISK_DUMP 2>/dev/null
#we need to check each entry, if its directory, go into it and get the youngest file
echo "Checking file age for ${DATA}, this will take a while, please wait..." >&2
for i in $(cat $DATA_RAW_DISK_DUMP | awk '{print $2}') ; do
if [[ -d $i ]] ; then
#we need to find the youngest file in this directory tree
YOUNGEST_FILE="$(find $i -type f -printf "%C# %p\n" | sort -rn | head -n 1|sed 's,[0-9]*[.][0-9]*[ ],,g')"
if [[ $YOUNGEST_FILE == "${i}" ]] ; then
stat --format "%n;%Y;%X;%U" "$i" >> $DATA_RAW_FILE_LIST 2>/dev/null
elif [[ $YOUNGEST_FILE == "" ]] ; then
stat --format "%n;%Y;%X;%U" "$i" >> $DATA_RAW_FILE_LIST 2>/dev/null
else
stat --format "%n;%Y;%X;%U" "$YOUNGEST_FILE" >> $DATA_RAW_FILE_LIST 2>/dev/null
fi
else
stat --format "%n;%Y;%X;%U" "$i" >> $DATA_RAW_FILE_LIST 2>/dev/null
fi
done
The script above, option 2 & 3 will work fine but option 1 show nothing. Then I try another way by adding another variable into the script and it did not work as well. Can someone show me how to make it read my file system /data?
echo "Please select from below:"
cat<<EOF
1. /data
2. /data01
3. DO_ALL_DATA_AT_ONCE
Press ENTER to exit
EOF
echo -n "Selection:"
read ans
if [[ $ans == "" ]] ; then
echo "Bye"
exit 0
fi
case $ans in
"1"|"2"|"3")
FS_TARGET="$ans"
;;
*)
echo "Unknown option - quitting"
echo "Bye"
exit 0
;;
esac
DATA="/data0${FS_TARGET}/*"
if [[ $FS_TARGET -eq 1 ]] ; then
#if the selection is 1, then change do the variable....
DATA="/data/*"
fi
if [[ $FS_TARGET -eq 3 ]] ; then
#if the selection is 3, then we just do everything, in one go
DATA="/data/* /data01/*"
fi
Related
#!/bin/bash
#variables
option=$1
myfile=~/.bdrecord.txt;
#supported options
opts=("-a" "--test" "-app" "-c" "-v");
argc=("ram ram nov 12 pen | --test" "" "1s|1m|1h" "" "");
flag=0;
for o in ${opts[#]}
do
if [[ $o = ${option} ]];
then
flag=1;
break
fi
done
if [[ ${flag} -ne 1 ]];
then
echo -e "Program aborted!\nSupported commands are like"
for i in ${!opts[#]};
do
echo -e "$i.\t" $0 ${opts[$i]} ${argc[$i]}
done
fi
#defaults
name="Rambo"
nickname="Ram"
bmth=$(date +%h);
bday=$(date +%d);
gift="hat-type"
#new feature, handle --test option along with -a option
if [[ ${option} = "-a" ]];
then
while read -r name nickn month day gift
do
if [[ ${2} = ${name} ]];
then
isRepeated=1;
break;
fi
done
if [[ isRepeated == 1 ]]
then
echo "${name} is a repeated name. Try again."
exit 22;
fi
if [[ ${2} = "--test" ]];
then
#add some test data and exit.
for ((i=0;i<5; i++))
do
row="${name}-$i,${nickname},${bmth},$(($bday+$i)),${gift}-${i}";
echo ${row} >> ${myfile}
done
echo "Saved 5 samples in ${myfile}";
echo "...";
tail -n 5 ${myfile};
echo -e ".." $(cat ${myfile} | wc -l) "entries"
exit 0;
fi
#handle more or less than 5 inputs
if [[ $# -ne 6 ]];
then
echo "Expected 5 args (name nickname month day gift) with -a option."
exit 22;
fi
echo "option -a is received!"
#save last 5 inputs in the file
##collect last 5 inputs
name=$2
nickname=$3
bmth=$4
bday=$5
gift=$6
row="${name},${nickname},${bmth},${bday},${gift}";
echo ${row} >> ${myfile}
#display current date
echo "Today: $(date)";
#display "yeah.."
echo "Yeah ${nickname} has been added!"
#display count of records
echo "--------"
wc -l ${myfile}
fi
#handle -c option
#handle -v option
#new feature, handle -app option
if [[ ${option} = "--app" ]];
then
if [[ $# -ne 2 ]];
then
echo "Expected arg sleep time {1s, 2s, 3s..1m, 2m, 3m, ..1h, 2h, 3h..}";
exit 44;
fi
echo "Entered App Mode. Use kill command to kill it."
#find person whose birthday is today
thismonth=$(date +"%h")
ithismonth=$(date +"%m")
thisday=$(date +"%d")
bdlist=();
while IFS="," read -r name nickn month day gift
do
if [[ ("${month,,}" = "${thismonth,,}" \
||
"${month,,}" -eq "${ithismonth,,}") ]] \
&& [[ ${day} = ${thisday} ]]
then
#add to list
bdlist+=("Today is ${name}'s $day birthday! Selected gift is:${gift} ")
fi
done < ${myfile}
while :
do
#every hour send three messages notifying whose birthday is today.
sleep ${2};
for l in "${bdlist[#]}";
do
echo "$l" >> ~/.bdlog.txt;
done
let i++;
done
fi
The instructions of my assignment clearly state to: Modify the given script so that for the "-a" option, the script stores the arguments (name, nickname, birthday month, birthday day, gift) in the file ~/.bdrecord.txt only if the given input name does not exist in the record file ~/.bdrecord.txt
However, my code is erroring. The part that I added is the part where isRepeated is.
I have a problem with pre-commit hook. The first half of the script works, but the second half that checks max size doesn't. Anyone have an idea what the problem is?
#!/bin/bash
REPOS=$1
TXN=$2
MAX_SIZE=10
AWK=/bin/awk
SVNLOOK="/usr/bin/svnlook";
#Put all banned extensions formats in variable FILTER
FILTER=".(iso|exe)$"
# Figure out what directories have changed using svnlook.
FILES=`${SVNLOOK} changed ${REPOS} -t ${TXN} | ${AWK} '{ print $2 }'` > /dev/null
for FILE in $FILES; do
#Get the base Filename to extract its extension
NAME=`basename "$FILE"`
#Get the extension of the current file
EXTENSION=`echo "$NAME" | cut -d'.' -f2-`
#Checks if it contains the restricted format
if [[ "$FILTER" == *"$EXTENSION"* ]]; then
echo "Your commit has been blocked because you are trying to commit a restricted file." 1>&2
echo "Please contact SVN Admin. -- Thank you" 1>&2
exit 1
fi
#check file size
filesize=$($SVNLOOK cat -t $TXN $REPOS $f|wc -c)
if [ "$filesize" -gt "$MAX_SIZE" ]; then
echo "File $f is too large(must <=$MAX_SIZE)" 1>&2
exit 1
fi
done
exit 0
OK, I made a little script to check filesize only
#!/bin/bash
REPOS=$1
TXN=$2
MAX_SIZE=10
AWK=/bin/awk
SVNLOOK="/usr/bin/svnlook";
#check file size
filesize=`${SVNLOOK} changed ${REPOS} -t ${TXN} | wc -c`
if [ "$filesize" -gt "$MAX_SIZE" ]; then
echo "File $filesize is too large" 1>&2
exit 1
fi
echo "File $filesize" 1>&2
exit 0
and when I try co commit file that have 25,5 MB, in output see only 20
File 20 is too large
Why its only 20 ? I think output must be on like 26826864 Bytes
Ok last wariuan of this script is
#!/bin/bash
REPOS=$1
TXN=$2
MAX_SIZE=10
svnlook="/usr/bin/svnlook";
size=$($svnlook filesize -t $TXN $REPOS $file)
if [[ "$size" -gt "$MAX_SIZE" ]] ; then
echo "File is too large" 1>&2
exit 1
fi
exit 0
But it still didnt work. Can someone write the correct variant of this please?
In that case, as I understand correctly, scrypt must look like below. But it still doesn't work, maybe someone knows what the problem is? Then I can add a file of whatever size.
#!/bin/bash
REPOS=$1
TXN=$2
maxsize=-1
svnlook="/usr/bin/svnlook";
svnlook -t $TXN changed | while read status file
do
[[ $status == "D" ]] && continue # Skip Deletions
[[ $file == */ ]] && continue # Skip directories
size=$(svnlook filesize -t $TXN $REPOS $file)
if [ $size -gt $maxsize ]]
then
echo "File '$file' too large to commit" >&2
exit 2
fi
done
exit 0
You made at least 2 errors, outside of code:
Didn't verify output of |wc -c by hand before using in hook (I can't recall format from memory)
Didn't RTFM carefully: piping of $SVNLOOK cat is unnecessary overcomplication, while you have subcommand filesize.
Addition
Code from referenced in my comment topic (re-read it carefully, don't miss cycle for getting every file in transaction)
svnlook -t $TXN changed | while read status file
do
[[ $status == "D" ]] && continue # Skip Deletions
[[ $file == */ ]] && continue # Skip directories
size=$(svnlook filesize -t $TXN $REPOS $file)
if [ $size -gt $maxsize ]]
then
echo "File '$file' too large to commit" >&2
exit 2
fi
done
exit 0
This wariant is working for me :)
#!/bin/bash
REPOS=$1
TXN=$2
MAX_SIZE=20971520
svnlook=/usr/bin/svnlook
AWK=/bin/awk
FILES=`${svnlook} changed -t ${TXN} ${REPOS} | ${AWK} '{print $2}'`
for FILE in $FILES; do
size=`${svnlook} filesize -t ${TXN} ${REPOS} ${FILES}`
if [[ "$size" -gt "$MAX_SIZE" ]] ; then
echo "Your commit has been blocked because you are trying to commit a too large file." 1>&2
exit 1
fi
done
exit 0
I'm trying to add options to my little safe delete script. For example, I can do ./sdell -s 100 and it will delete files with size above 100 kbs. Anyway, I'm having problems with my safe guard function.
#!/bin/bash
#Purpose = Safe delete
#Created on 20-03-2018
#Version 0.8
#jesus,i'm dumb
#START
##Constants##
dir="/home/cunha/LIXO"
#check to see if the imputs are a files#
for input in "$#"; do
if ! [ -e "$input" ]; then
echo "Input is NOT a file!"
exit 1
fi
done
###main###
case $1 in
-r) echo "test option -r"
;;
*) if [[ -f "$dir/$fwe.tar.bz2" ]]; then
echo "File already exists."
if [[ "$file" -nt "$2" ]]; then
echo "Removing older file." && rm "$dir"/"$fwe.tar.bz2" && tar -czPf "$fwe.tar.bz2" "$(pwd)" && mv "$fwe.tar.bz2" "$d$
fi
else
echo "Ziping it and moving." && tar -czPf "$fwe.tar.bz2" "$(pwd)" && mv "$fwe.tar.bz2" "$dir"
fi
done
;;
esac
The problem is when I call ./sdell -r file1.txt, it says that the input is not a file.
Here is the script without the case, 100% working before having options.
#!/bin/bash
#Purpose = Safe delete
#Created on 20-03-2018
#Version .7
#START
##Constants##
dir="/home/cunha/LIXO"
#check to see if the imputs are a files#
for input in "$#"; do
if ! [ -e "$input" ]; then
echo "Input is NOT a file!"
exit 0
fi
done
###main###
##Cycle FOR so the script accepts multiple file inputs##
for file in "$#"; do
fwe="${file%.*}"
#IF the input file already exist in LIXO#
if [[ -f "$dir/$fwe.tar.bz2" ]]; then
echo "File already exists."
#IF the input file is newer than the file thats already in LIXO#
if [[ "$file" -nt "$2" ]]; then
echo "Removing older file." && rm "$dir"/"$fwe.tar.bz2" && tar -czPf "$fwe.tar.bz2" "$(pwd)" && mv "$fwe.tar.bz2" "$d$
fi
else
echo "Ziping it and moving." && tar -czPf "$fwe.tar.bz2" "$(pwd)" && mv "$fwe.tar.bz2" "$dir"
fi
done
The message you are seeing is unrelated to the case..esac, construct, it is printed by this section:
for input in "$#"; do
if ! [ -e "$input" ]; then
echo "Input is NOT a file!"
exit 1
fi
done
which expands all command-line parameters ($#), including the "-r", and exits the script because "-r" is not a file. The case..esac is never reached. You can run your script with
bash -x file.sh -r test
so that you can see exactly which lines are being executed.
The snippet below probably does what you want, processing all arguments sequentially:
#!/bin/bash
while [ ! -z $1 ]; do
case $1 in
-r) echo "option R"
;;
-f) echo "option F"
;;
*) if [ -f $1 ]; then echo "$1 is a file." ; fi
;;
esac
shift
done
Consider checking if -r has been passed before trying other options and use shift if it was:
#!/usr/bin/env sh
dir="/home/cunha/LIXO"
case $1 in
-r) echo "test option -r"
shift
;;
esac
#check to see if the imputs are a files#
for input in "$#"; do
echo current input: "$input"
if ! [ -e "$input" ]; then
echo "Input $input is NOT a file!"
exit 1
fi
done
if [[ -f "$dir/$fwe.tar.bz2" ]]; then
echo "File already exists."
if [[ "$file" -nt "$2" ]]; then
echo "Removing older file..."
# add stuff
fi
else
echo "Ziping it and moving."
# add stuff
fi
have some problem with shell script.
In our office we set up only few commands, that available for devs when they are trying ssh to server. It is configured with help of .ssh/authorized_keys file and available command for user there is bash script:
#!/bin/sh
if [[ $1 == "--help" ]]; then
cat <<"EOF"
This script has the purpose to let people remote execute certain commands without logging into the system.
For this they NEED to have a homedir on this system and uploaded their RSA public key to .ssh/authorized_keys (via ssh-copy-id)
Then you can alter that file and add some commands in front of their key eg :
command="/usr/bin/dev.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
The user will do the following : ssh testuser#server tail testserver.example.com/2017/01/01/user.log
EOF
exit 0;
fi
# set global variable
set $SSH_ORIGINAL_COMMAND
# set the syslog path where the files can be found
PATH="/opt/syslog/logs"
# strip ; or any other unwanted signs out of the command, this prevents them from breaking out of the setup command
if [[ $1 != "" ]]; then
COMMAND=$1
COMMAND=${COMMAND//[;\`]/}
fi
if [[ $2 != "" ]]; then
ARGU1=$2
ARGU1=${ARGU1//[;\`]/}
fi
if [[ $3 != "" ]]; then
ARGU2=$3
ARGU2=${ARGU2//[;\`]/}
fi
if [[ $4 != "" ]]; then
ARGU3=$4
ARGU3=${ARGU3//[;\`]/}
fi
# checking for the commands
case "$COMMAND" in
less)
ARGU2=${ARGU1//\.\./}
FILE=$PATH/$ARGU1
if [ ! -f $FILE ]; then
echo "File doesn't exist"
exit 1;
fi
#echo " --------------------------------- LESS $FILE"
/usr/bin/less $FILE
;;
grep)
if [[ $ARGU2 == "" ]]; then
echo "Pls give a filename"
exit 1
fi
if [[ $ARGU1 == "" ]]; then
echo "Pls give a string to search for"
exit 1
fi
ARGU2=${ARGU2//\.\./}
FILE=$PATH/$ARGU2
/usr/bin/logger -t restricted-command -- "------- $USER Executing grep $ARGU1 \"$ARGU2\" $FILE"
if [ ! -f $FILE ]; then
echo "File doesn't exist"
/usr/bin/logger -t restricted-command -- "$USER Executing $#"
exit 1;
fi
/bin/grep $ARGU1 $FILE
;;
tail)
if [[ $ARGU1 == "" ]]; then
echo "Pls give a filename"
exit 1
fi
ARGU1=${ARGU1//\.\./}
FILE=$PATH/$ARGU1
if [ ! -f $FILE ]; then
echo "File doesn't exist"
/usr/bin/logger -t restricted-command -- "$USER Executing $# ($FILE)"
exit 1;
fi
/usr/bin/tail -f $FILE
;;
cat)
ARGU2=${ARGU1//\.\./}
FILE=$PATH/$ARGU1
if [ ! -f $FILE ]; then
echo "File doesn't exist"
exit 1;
fi
/bin/cat $FILE
;;
help)
/bin/cat <<"EOF"
# less LOGNAME (eg less testserver.example.com/YYYY/MM/DD/logfile.log)
# grep [ARGUMENT] LOGNAME
# tail LOGNAME (eg tail testserver.example.com/YYYY/MM/DD/logfile.log)
# cat LOGNAME (eg cat testserver.example.com/YYYY/MM/DD/logfile.log)
In total the command looks like this : ssh user#testserver.example.com COMMAND [ARGUMENT] LOGFILE
EOF
/usr/bin/logger -t restricted-command -- "$USER HELP requested $#"
exit 1
;;
*)
/usr/bin/logger -s -t restricted-command -- "$USER Invalid command $#"
exit 1
;;
esac
/usr/bin/logger -t restricted-command -- "$USER Executing $#"
The problem is next:
when i try to exec some command, it takes only first argument, if i do recursion in files by using {n,n1,n2} - it doesn't work:
[testuser#local ~]$ ssh testuser#syslog.server less srv1838.example.com/2017/02/10/local1.log |grep 'srv2010' | wc -l
0
[testuser#local ~]$ ssh testuser#syslog.server less srv2010.example.com/2017/02/10/local1.log |grep 'srv2010' | wc -l
11591
[testuser#local ~]$ ssh testuser#syslog.server less srv{1838,2010}.example.com/2017/02/10/local1.log |grep 'srv2010' | wc -l
0
[testuser#local ~]$ ssh testuser#syslog.server less srv{2010,1838}.example.com/2017/02/21/local1.log |grep 'srv2010' | wc -l
11591
Could someone help me, how can i parse\count command arguments to make it work?
Thank you and have a nice day!
The number of arguments for a bash script would be $#. As a quick example:
#!/bin/bash
narg=$#
typeset -i i
i=1
while [ $i -le $narg ] ; do
echo " $# $i: $1"
shift
i=$i+1
done
gives, for bash tst.sh a b {c,d}
4 1: a
3 2: b
2 3: c
1 4: d
In your script, the command to execute (cat, less, ...) gets explicitly only the second argument to the script. If you want to read all arguments, you should do something like this (note: only a hint, removed all sorts of checks etc..)
command="$1"
shift
case $command in
(grep) pattern="$1"
shift
while [ $# -gt 0 ] ; do
grep "$pattern" "$1"
shift
done
;;
esac
note: added some quotes as comment suggested, but, being only a hint, you should carefully look at quoting and your checks in your own script.
Less command working now:
case "$COMMAND" in
less)
if [[ $ARGU1 == "" ]]; then
echo "Pls give a filename"
exit 1
fi
FILES_LIST=${#:2}
FILE=(${FILES_LIST//\.\./})
for v in "${FILE[#]}";do
v=${v//[;\']/}
if [ ! -f $v ]; then
echo "File doesn't exist"
fi
/usr/bin/less $PATH/$v
done;;
tail command works too with 2 and more files, but i can't execute tail -f command on two files unfortunately.
I need to create one file list for below files:
APPLE_001
APPLE_002
BBB_004
APPLE_003
I need to create file_list only for
APPLE_001
APPLE_002
APPLE_003
Thanks,
Ipsita
Your specifications are not that narrow, but here a bash script that match your request :
#!/bin/bash
if [[ $# < 2 ]]
then
echo "[ERROR] this script expects two arguments, input file and output file" >&2
exit 1
fi
input_file=$1
output_file=$2
if [[ ! -f $input_file ]]
then
echo "[ERROR] your input file '$input_file' is missing" >&2
exit 1
fi
if [[ -f $output_file ]]
then
echo "[ERROR] your output file '$ouput_file' already exists please move it away" >&2
exit 1
fi
while read LINE
do
if [[ $LINE =~ APPLE_[0-9]+ ]]
then
echo $LINE >> $output_file
else
echo "'$LINE' does not match expected pattern, skip it"
fi
done < $input_file
if [[ -f $ouput_file ]]
then
echo "'$output_file' generated."
else
echo "[WARNING] no pattern found in '$input_file' no file generated"
fi
make it executable ( chmod +x ./list_starting_with.sh )
run it with ./list_starting_with.sh file_in.txt file_out.txt