Error With Bash Script [duplicate] - linux

This question already has answers here:
Are shell scripts sensitive to encoding and line endings?
(14 answers)
Closed 3 years ago.
I would like to know what is the error in the below script
i get error as : command not foundh: line 1: , : command not foundh: line 2: its continuous
i have tried add ; but now working kindly tell me what to do ??
#!/bin/bash;
clear;
FILEREPO=http://192.168.1.2/cpplugin;
echo "-----------------------------------------------";
echo " Welcome to C-Panel Login Alert Installer";
echo "-----------------------------------------------";
cd /var/cpanel/;
mkdir perl5
cd perl5/
mkdir lib
cd lib/
wget $FILEREPO/LoginAlerthook.zip
unzip LoginAlerthook.zip
rm -r LoginAlerthook.zip
cd /
/usr/local/cpanel/bin/manage_hooks add module LoginAlert
chmod 777 LoginAlert.pm
echo " "
echo " Login Alert Script Hooked With C Panel Finished"
echo " "

The fact that you're getting the funny output is a sure bet that your script has carriage return (CR) characters at the end of the lines, usually a symptom of using Windows editors that assume line endings should be CR/LF rather than just the standard UNIX LF (linefeed). That is causing error output like:
this_command_ends_hh<CR>: command not found
and because the CR is putting the cursor back at line start, it's overwriting some of it:
this_command_ends_hh<CR>
: command not found
making:
: command not foundh
Examine your script with od -xcb scriptname to check for CR (displayed as \r) characters, you can also pipe the script output through od -xcb to see the real output. For example is a file I created with hello followed by a carriage return on the one and only line:
0000000 6568 6c6c 0d6f 000a
h e l l o \r \n
150 145 154 154 157 015 012
0000007
You can see the CR (\r) in there.
If that is the problem, simply remove the CR characters such as piping it through tr -d '\r'.
Executing cat hello.txt | tr -d '\r' | od -xcb shows that you can get rid of it:
0000000 6568 6c6c 0a6f
h e l l o \n
150 145 154 154 157 012
0000006
In your case, assuming your script is called freak.bash, you would use:
tr -d '\r' <freak.bash >newfreak.bash
and newfreak.bash would be the one without the offending characters.

A tool you can use to understand what is happening in the execution of this script in order to debug is the command,
bash -x scriptname.sh

paxdiablo is almost certainly correct: you need to fix the line endings. But you also have an errant semi-colon in the first line. Instead of:
#!/bin/bash;
you want:
#!/bin/bash
without the trailing semi-colon.

I don't have a Centos 5 right now, but maybe... just maybe... bash isn't located at /bin? In FreeBSD, it's located at /usr/local/bin. In Cygwin, it's at /usr/bin. What's the output of this command:
which bash

paxdiablo and William Pursell nicely explained what the problem is.
Now, please take the time to improve your script if you're going to distribute it.
NOT TESTED example:
#/bin/bash
ZIPFILE=http://192.168.1.2/cpplugin/LoginAlerthook.zip
CPANEL_LIBDIR=/var/cpanel/perl5/lib
MANAGE_HOOKS_CMD=/usr/local/cpanel/bin/manage_hooks
TMPFILE=`tempfile`
function exit_with_error(){
echo "$*" >&2 # Write error messages to stderr!!
exit 1
}
function at_exit(){
[ -f "${TMPFILE}" ] && rm -v ${TMPFILE}
}
# Run at_exit function when script finishes
trap at_exit 0
echo "WELCOME TO ZOMBO.COM"
# Create lib directory if not exists, exit if not possible
if ! [ -d "${CPANEL_LIBDIR}" ]; then
mkdir -p ${CPANEL_LIBDIR} || exit_with_error "Couldn't create required directory [${CPANEL_LIBDIR}]"
fi
wget ${ZIPFILE} -O ${TMPFILE} || exit_with_error "Couldn't download file"
unzip -d ${CPANEL_LIBDIR} ${TMPFILE} || exit_with_error "Couldn't unzip file"
chmod +x ${CPANEL_LIBDIR}/LoginAlert.pm || exit_with_error "Couldn't chmod file"
$MANAGE_HOOKS_CMD add module LoginAlert
echo "End."
This is just a dirty example. Read the manpages to improve.
man bash
man tempfile
man wget
man unzip
man chmod

Related

To remove whitespace or newline for the string value fetched from the text file

sample.txt file contains below values
1111
2222
3333
With above values will be frames to access the folder with names 1111, 2222, 3333
I'm referring these values using below code
for i in $(cat sample.txt); do cd folder1/$i; done
it gives error as can't cd : folder1/1111
Reason because each string values referred from the file has some suffice whitespace or new line character ..not sure exactly
I tried below commands with no success
for i in $(cat sample.txt); do i = $(echo ${i::-1 }); cd folder1/$i; done
for i in $(cat sample.txt); do i = $(echo $i | tr -d "[:space:]"); cd folder1/$i; done
for i in $(cat sample.txt); do cd folder1/$i; done
I guess you don't get the error for the first line, but starting from the second line only.
If you have successfully done
cd folder1/1111
the command
cd folder1/2222
will fail because you already are in folder1/1111.
You should cd back to the original directory or do the cd and whatever else you want to do in a subshell.
BTW: You should not read the lines with for, because this will fail if you have a line that contains a space.
See https://mywiki.wooledge.org/DontReadLinesWithFor
and https://mywiki.wooledge.org/BashFAQ/001.
This should work
while read -r dir
do
( cd "folder1/$dir" ) # ( ... ) to use a subshell
# after leaving the subshell, here we are back in the original directory
done < sample.txt

Bash read -p doesnt work [duplicate]

This question already has answers here:
': not a valid identifier [duplicate]
(4 answers)
Why would a correct shell script give a wrapped/truncated/corrupted error message? [duplicate]
(1 answer)
Closed 5 years ago.
When running my shell script I get this error:
': not a valid identifiere 17: read: `
Here is my shell script:
#!/usr/bin/env bash
# Mr. Robot Install Wordpress Script
# Script is used for the following:
# add user to server
# change to new user home directory
# download latest version of wordpress
# unzip wordpress
# move all files up a directory level
# move up a directory level
# delete wordpress.zip
# remove wordpress folder
echo "/*****************************************************/"
echo "/************** HELLO MR. ROBOT **********************/"
echo "/*****************************************************/"
echo ".."
echo ".."
echo "Website URL"
echo 'url: \r'
read -p $website
echo 'User: \r'
read -p $newuser
echo 'Pass: \r'
read -p $password
echo "creating account......"
/scripts/wwwacct $website $newuser $password 0 x3 n n n 0 0 0 0 0 0
echo "Changing Directory....."
cd ~/home/$newuser/
echo "Getting Latest Version of Wordpress!"
curl -O http://wordpress.org/latest.tar.gz
echo "Tarball Incoming!!"
tar xvzf latest.tar.gz
echo "removing tar file"
rm latest.tar.gz
echo "moving wordpress folders!"
cp -a ~/home/$newuser/public_html/wordpress/. ~/home/$newuser/public_html/
cd /home/$newuser/public_html/
echo "Part 01 Complete!!"
exit
I've tried to use different versions of the read line with -p or -e. Any help would be appreciated. I've even tried adding it on a separate line with input.
EDIT: Updated file to where it takes inputs, but issue is that the inputs are not being used through the rest of the script. Thus causing errors for directories not being found.
Don't quote the variables names. read needs the name of the variable to assign to, not its value, which is what you get if you have a dollar sign $.
read -p 'website url: ' website
read -p 'Username: ' newuser
read -p 'Password: ' password
It looks like one of the variables holds \r, a carriage return. The error message that bash is trying to print is something like:
bash: ./script: line 17: read: `\r': not a valid identifier
But \r causes the cursor to go back to the beginning of the line, causing ': not a valid identifier to overwrite the beginning of the message.
As mentioned above by John Kugelman, in case you have to check if you Input_file is having carriage returns then you could run following command:
cat -v Input_file
In case you find them then try to remove them from either of following cmmands:
tr -d '\r' < Input_file
OR
awk '{gsub(/\r/,"")} 1' Input_file
Or check if your system(box) has dos2unix utility you could use that also for removing these carriage returns.

Errors "No such file or directory" ,"command not found" seen while running my shell script

The contents of my script
`sqlline.py tpxxx.entexxx.org <<END
!outputformat csv
!record /ap_data/DD3/Rawf/Raw_f_$1_$2.csv
select column1,column2,column3,column4 from DD3_vxxv_$1.DD3_vv_RAW_DATA where v_id=$3 and period=$4;
!record
!quit
END;`
`sed -i '1d;$d' /ap_data/DD3/Rawf/Raw_f_$1_$2.csv;
sed -i "s/'//g" /ap_data/DD3/Rawf/Raw_f_$1_$2.csv;
cd /ap_data/D2O/RawDownload/
zip Raw_f_$1_$2.zip Raw_f_$1_$2.csv;
scp Raw_f_$1_$2.zip txxx#daxxxx.entexxx.org:/opt/cdar/common/D2O/TabUpload/;
rm Raw_f_$1_$2.csv Raw_f_$1_$2.zip;`
On executing the script:
./rawfile.sh: line 7: 0/?: No such file or directory
./rawfile.sh: line 13: adding:: command not found
The script gives correct output. But still shows the errors "No such file or directory", "command not found"
My file permission is: -rwxrwxrwx
Your script has backquotes around two main executable sections.
Backquotes cause the content within to be executed in a subshell and substituted back into your script. This means that in your case, your script is executing TWO commands. One of them is the output of the first backquoted expression, and the other is the output of the second backquoted expression.
For example:
$ `echo hello`
bash: hello: command not found
$ `echo echo hello`
hello
What's happening here is that the first echo command generates output which is substituted into your command line, making the command line evaluated by the shell simply "hello" .. which is not a command. The second command line prints "echo hello", which is a valid command line and evaluates to something that prints "hello".
Remove the backquotes from around your two main statements, and just execute the commands directly.
#!/bin/sh
sqlline.py tpxxx.entexxx.org <<END
!outputformat csv
!record /ap_data/DD3/Rawf/Raw_f_$1_$2.csv
select column1,column2,column3,column4 from DD3_vxxv_$1.DD3_vv_RAW_DATA where v_id=$3 and period=$4;
!record
!quit
END
sed -i '1d;$d' /ap_data/DD3/Rawf/Raw_f_$1_$2.csv
sed -i "s/'//g" /ap_data/DD3/Rawf/Raw_f_$1_$2.csv
cd /ap_data/D2O/RawDownload/
zip Raw_f_$1_$2.zip Raw_f_$1_$2.csv
scp Raw_f_$1_$2.zip txxx#daxxxx.entexxx.org:/opt/cdar/common/D2O/TabUpload/
rm Raw_f_$1_$2.csv Raw_f_$1_$2.zip

prompt list of files before execution of rm

I started using "sudo rm -r" to delete files/directories. I even put it as an alias of rm.
I normally know what I am doing and I am quite experience linux user.
However, I would like that when I press the "ENTER", before the execution of rm, a list of files will show up on the screen and a prompt at the end to OK the deletion of files.
Options -i -I -v does not do what I want. I want only one prompt for all the printed files on screen.
Thank you.
##
# Double-check files to delete.
delcheck() {
printf 'Here are the %d files you said you wanted to delete:\n' "$#"
printf '"%s"\n' "$#"
read -p 'Do you want to delete them? [y/N] ' doit
case "$doit" in
[yY]) rm "$#";;
*) printf 'No files deleted\n';;
esac
}
This is a shell function that (when used properly) will do what you want. However, if you load the function in your current shell then try to use it with sudo, it won't do what you expect because sudo creates a separate shell. So you'd need to make this a shell script…
#!/bin/bash
… same code as above …
# All this script does is create the function and then execute it.
# It's lazy, but functions are nice.
delcheck "$#"
…then make sure sudo can access it. Put it in some place that is in the sudo execution PATH (Depending on sudo configuration.) Then if you really want to execute it precisely as sudo rm -r * you will still need to name the script rm, (which in my opinion is dangerous) and make sure its PATH is before /bin in your PATH. (Also dangerous). But there you go.
Here's a nice option
Alias rm to echo | xargs -p rm
The -p option means "interactive" - it will display the entire command (including any expanded file lists) and ask you to confirm
It will NOT ask about the recursively removed files. But it will expand rm * .o to:
rm -rf * .o
rm -rf program.cc program.cc~ program program.o backup?... # NO NO NO NO NO!
Which is much nicer than receiving the error
rm: .o file not found
Edit: corrected the solution based on chepner comment. My previous solutions had a bug :(
This simple script prompts for a y response before deleting the files specified.
rmc script file:
read -p "ok to delete? " ans
case $ans in
[yY]*) sudo rm "$#" ;;
*) echo "Nothing deleted";;
esac
Invoke thus
./rmc *.tmp
I created a script to do this. The solution is similar to #kojiro's.
Save the script with the filename del. Run the command sudo chmod a=r+w+x del to make the script an executable. In the directory in which you want to save the script, export the path by entering export PATH=$PATH:/path/to/the/del/executable in your '~/.bashrc' file and run source ~/.bashrc.
Here, the syntax of rm is preserved, except instead of typing rm ..., type del ... where del is the name of the bash script below.
#! /bin/bash
# Safely delete files
args=("$#") # store all arguments passed to shell
N=$# # number of arguments passed to shell
#echo $#
#echo $#
#echo ${args[#]:0}
echo "Files to delete:"
echo
n=`expr $N - 1`
for i in `seq 0 $n`
do
str=${args[i]}
if [ ${str:0:1} != "-" ]; then
echo $str
fi
done
echo
read -r -p "Delete these files? [y/n] " response
case $response in
[yY][eE][sS]|[yY])
rm ${args[#]:0}
esac

Get substring from Start Index to End Index

I'm working on this for two hours but no luck, always the "Bad substitution" error.
What I want to make (.sh script):
Read from file (names), then I'd like to substitute this name with substring of the given name by the offset and lenght which are the script arguments ($1 = offset, $2 = lenght).
It should work like this (I think) : new_user=${user:$1:$2}
-> where user is read from .txt (in while loop) and $1 and $2 are arguments of this .sc
I've highlighted the important part:
#!/bin/bash
touch postopek.log
while IFS="," read fullName userName passwordLarge
do
pass=$(perl -e 'print crypt(&ARGV[0], "password")' $passwordLarge)
new_up=${fullName:$1:$2} # important line
sudo useradd -m -p $pass -d /home/$new_up -s /bin/bash $new_up
[ $? -eq 0] && echo "Made something bla bla not important..." >> postopek.log
sudo mkdir /home/$new_up/gradivo
sudo cp -r /home/administrator/vaje/* /home/$new_up/gradivo
sudo chown -R $new_up:$new_up /home/$new_up/gradivo
done < /home/administrator/seznam.txt
The sh shell you are running the script with is probably not bash, try running it like
bash ustvari.sh 3 5
or just
/path/to/ustvari.sh 3 5
since your shebang points to bash anyway.
${parameter:offset:length} is not specified by POSIX, thus if your /bin/sh is a shell which does not support the substring syntax, you get the Bad substitution error you encountered, for example:
$ dash
$ echo ${foo:0:1}
dash: 1: Bad substitution

Resources