Thank you for reviewing my shell script i am producing this error but not sure why it is not running. I am a noob when it comes to shell scripting. Please help. Here is my code:
#!/bin/bash
#This script creates the log files based on the current date and hour
#Variables for managing the logs
LOG_DIRECTORY=/var/log; export LOG_DIRECTORY
LOG_DIRECTORY_FILE=/var/log/secure; export LOG_DIRECTORY_FILE
MY_LOG_DIRECTORY=$LOG_DIRECTORY/mylogs; export MY_LOG_DIRECTORY
MY_LOG_FILE=$MY_LOG_DIRECTORY/mylog-`date +%m-%d-%H`; export MY_LOG_FILE
EXPRESSTION=`date '+%b %d %H'`; export MY_LOG_FILE
#Checks if mylog directory exists.If not, then creates it
if [ ! -d "$MY_LOG_DIRECTORY" ]; then
mkdir -p $MY_LOG_DIRECTORY
fi
#Scripts exits successfully, If the log already exists
if [ -f "$MY_LOG_FILE" ]; then
echo "Log file already exists. Nothing is written to log";
exit 0;
fi
#grep the contents to the log file
grep "^$EXPRESSTION" $LOG_DIRECTORY_FILE >> $MY_LOG_FILE
echo "New myLog file created successfully"
Your script needs to be saved as a UNIX text file.
Try running dos2unix on it, or open it up in vim and run :set fileformat=unix and save.
If you don't have dos2unix, and aren't comfortable with vim, you can use perl:
perl -pi -e 's/\r\n?/\n/g' your-script-filename
"bad interpreter no such file or directory" error indicates /bin/bash does not exist.
Try to run script as
$ sh log.sh
OR use some other available shell interpreter (e.g /bin/sh , /bin/ksh) instead of /bin/bash
Related
I am a new user learning to use Linux. I am currently running Ubuntu 18.04 with several aliases created, and saved in the ~/.bashrc directory. I am trying to write a welcome script that also displays the current aliases upon start up. The current code I have is as follows:
#! /bin/bash
echo -e "\nWelcome $USER"
echo -e "Today's date is: \c"
date
echo -e "\vHave \vA \VGreat \vDay! \c"
echo -e "\nCurrent aliases for reference are:"
alias
Upon startup, or running the script on it's own, the welcome message runs but the actual alias command does not?
First things first:
(...) saved in the ~/.bashrc directory. (...)
Well, I must point that .bashrc is a file, not a directory, and is part of the Bash startup files.
That said, the reason why running the alias command inside a script does not work as expected is that it is a shell builtin, and when invoking it from a script will not behave as if running it from your shell.
Hence, the quickest thing you can do is store your aliases in a different file, like ~/.bash_aliases and ensure it will be loaded by adding this to your .bashrc file:
if [ -f ~/.bash_aliases ]; then
source ~/.bash_aliases
fi
And then read that file directly from your script:
#! /bin/bash
echo -e "\nWelcome $USER"
echo -e "Today's date is: \c"
date
echo -e "\vHave \vA \VGreat \vDay! \c"
echo -e "\nCurrent aliases for reference are:"
cat ~/.bash_aliases
I have a bash script in a file named reach.sh.
This file is given exe rights using chmod 755 /Users/vb/Documents/util/bash/reach.sh.
I then created an alias using alias reach='/Users/vb/Documents/util/bash/reach.sh'
So far this works great.
It happens that I need to run this script in my current process, so theoretically I would need to add . or source before my script path.
So I now have alias reach='source /Users/vb/Documents/util/bash/reach.sh'
At this point when I run my alias reach, the script is failing.
Error /Users/vb/Documents/util/bash/reach.sh:7: = not found
Line 7 if [ "$1" == "cr" ] || [ "$1" == "c" ]; then
Full script
#!/bin/bash
# env
REACH_ROOT="/Users/vb/Documents/bitbucket/fork/self"
# process
if [ "$1" == "cr" ] || [ "$1" == "c" ]; then
echo -e "Redirection to subfolder"
cd ${REACH_ROOT}/src/cr
pwd
else
echo -e "Redirection to root folder"
cd ${REACH_ROOT}
pwd
fi
Any idea what I could be missing ?
I'm running my script in zsh which is not a bash shell, so when I force it to run in my current process it runs in a zsh shell and does not recognize bash commands anymore.
In your question, you say "It happens that I need to run this script in my current process", so I'm wondering why you are using source at all. Just run the script. Observe:
bash-script.sh
#!/bin/bash
if [ "$1" == "aaa" ]; then
echo "AAA"
fi
zsh-script.sh
#!/bin/zsh
echo "try a ..."
./bash-script.sh a
echo "try aaa ..."
./bash-script.sh aaa
echo "try b ..."
./bash-script.sh b
output from ./zsh-script.sh
try a ...
try aaa ...
AAA
try b ...
If, in zsh-script.sh, I put source in front of each ./bash-script.sh, I do get the behavior you described in your question.
But, if you just need to "run this script in my current process", well, then ... just run it.
source tries to read a file as lines to be interpreted by the current shell, which is zsh as you have said. But simply running it, causes the first line (the #!/bin/bash "shebang" line) to start a new shell that interprets the lines itself. That will totally resolve the use of bash syntax from within a zsh context.
This question already has answers here:
Why can't I change directories using "cd" in a script?
(33 answers)
Closed 7 years ago.
What I'm trying to do
I've created a shell script that I've added to my $PATH that will download and get everything setup for a new Laravel project. I would like the script to end by changing my terminal directory into the new project folder.
From what I understand right now currently it's only changing the directory of the sub shell where the script is actually running. I can't seem to figure out how to do this. Any help is appreciated. Thank you!
#! /usr/bin/env bash
echo -e '\033[1;30m=========================================='
## check for a directory
if test -z "$1"; then
echo -e ' \033[0;31m✖ Please provide a directory name'
exit
fi
## check if directory already exist
if [ ! -d $1 ]; then
mkdir $1
else
echo -e ' \033[0;31m✖ The '"$1"' directory already exists'
exit
fi
# move to directory
cd $1
## Download Laravel
echo -e ' \033[0;32m+ \033[0mDownloading Laravel...'
curl -s -L https://github.com/laravel/laravel/zipball/master > laravel.zip
## Unzip, move, and clean up Laravel
echo -e ' \033[0;32m+ \033[0mUnzipping and cleaning up files...'
unzip -q laravel.zip
rm laravel.zip
cd *-laravel-*
mv * ..
cd ..
rm -R *-laravel-*
## Make the /storage directory writable
echo -e ' \033[0;32m+ \033[0mMaking /storage directory writable...'
chmod -R o+w storage
## Download and install the Generators
echo -e ' \033[0;32m+ \033[0mInstalling Generators...'
curl -s -L https://raw.github.com/JeffreyWay/Laravel-Generator/master/generate.php > application/tasks/generate.php
## Update the application key
echo -e ' \033[0;32m+ \033[0mUpdating Application Key...'
MD5=`date +”%N” | md5`
sed -ie 's/YourSecretKeyGoesHere!/'"$MD5"'/' application/config/application.php
rm application/config/application.phpe
## Create .gitignore and initial git if -git is passed
if [ "$2" == "-git" ]; then
echo -e ' \033[0;32m+ \033[0mInitiating git...'
touch .gitignore
curl -s -L https://raw.github.com/gist/4223565/be9f8e85f74a92c95e615ad1649c8d773e908036/.gitignore > .gitignore
# Create a local git repo
git init --quiet
git add * .gitignore
git commit -m 'Initial commit.' --quiet
fi
echo -e '\033[1;30m=========================================='
echo -e ' \033[0;32m✔ Laravel Setup Complete\033[0m'
## Change parent shell directory to new directory
## Currently it's only changing in the sub shell
filepath=`pwd`
cd "$filepath"
You can technically source your script to run it in your parent shell instead of spawning a subshell to run it. This way whatever changes you make to your current shell (including changing directories) persist.
source /path/to/my/script/script
or
. /path/to/my/script/script
But sourcing has its own dangers, use carefully.
(Peripherally related: how to use scripts to change directories)
Use a shell function to front-end your script
setup () {
# first, call your big script.
# (It could be open-coded here but that might be a bit ugly.)
# then finally...
cd someplace
}
Put the shell function in a shell startup file.
Child processes (including shells) cannot change current directory of parent process. Typical solution is using eval in the parent shell. In shell script echo commands you want to run by parent shell:
echo "cd $filepath"
In parent shell, you can kick the shell script with eval:
eval `sh foo.sh`
Note that all standard output will be executed as shell commands. Messages should output to standard error:
echo "Some messages" >&2
command ... >&2
This can't be done. Use exec to open a new shell in the appropriate directory, replacing the script interpreter.
exec bash
I suppose one possibility would be to make sure that the only output of your script is the path name you want to end up in, and then do:
cd `/path/to/my/script`
There's no way your script can directly affect the environment (including it's current directory) of its parent shell, but this would request that the parent shell itself change directories based on the output of the script...
this topic has been discussed at length, however, I have a variant on the theme that I just cannot crack. Two days into this now and decided to ping the community. THx in advance for reading..
Exec. summary is I have a script in OS X that runs fine and executes without issue or error when done manually. When I put the script in the crontab to run daily it still runs but it doesnt run all of the commands (specifically SFTP).
I have read enough posts to go down the path of environment issues, so as you will see below, I hard referenced the location of the SFTP in the event of a PATH issue...
The only thing that I can think of is the IdentityFile. NOTE: I am putting this in the crontab for my user not root. So I understand that it should pickup on the id_dsa.pub that I have created (and that has already been shared with the server)..
I am not trying to do any funky expect commands to bypass the password, etc. I dont know why when run from the cron that it is skipping the SFTP line.
please see the code below.. and help is greatly appreciated.. thx
#!/bin/bash
export DATE=`date +%y%m%d%H%M%S`
export YYMMDD=`date +%y%m%d`
PDATE=$DATE
YDATE=$YYMMDD
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
FEED="~/Dropbox/"
USER="user"
HOST="host.domain.tld"
A="/tmp/5nPR45bH"
>${A}.file1${PDATE}
>${A}.file2${PDATE}
BYEbye ()
{
rm ${A}.file1${PDATE}
rm ${A}.file2${PDATE}
echo "Finished cleaning internal logs"
exit 0
}
echo "get -r *" >> ${A}.file1${PDATE}
echo "quit" >> ${A}.file1${PDATE}
eval mkdir ${FEED}${YDATE}
eval cd ${FEED}${YDATE}
eval /usr/bin/sftp -b ${A}.file1${PDATE} ${USER}#${HOST}
BYEbye
exit 0
Not an answer, just comments about your code.
The way to handle filenames with spaces is to quote the variable: "$var" -- eval is not the way to go. Get into the habit of quoting all variables unless you specifically want to use the side effects of not quoting.
you don't need to export your variables unless there's a command you call that expects to see them in the environment.
you don't need to call date twice because the YYMMDD value is a substring of the DATE: YYMMDD="${DATE:0:6}"
just a preference: I use $HOME over ~ in a script.
you never use the "file2" temp file -- why do you create it?
since your sftp batch file is pretty simple, you don't really need a file for it:
printf "%s\n" "get -r *" "quit" | sftp -b - "$USER#$HOST"
Here's a rewrite, shortened considerably:
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
FEED_DIR="$HOME/Dropbox/$(date +%Y%m%d)"
USER="user"
HOST="host.domain.tld"
mkdir "$FEED_DIR" || { echo "could not mkdir $FEED_DIR"; exit 1; }
cd "$FEED_DIR"
{
echo "get -r *"
echo quit
} |
sftp -b - "${USER}#${HOST}"
I am attempting to write a bash script that changes directory and then runs an existing script in the new working directory.
This is what I have so far:
#!/bin/bash
cd /path/to/a/folder
./scriptname
scriptname is an executable file that exists in /path/to/a/folder - and (needless to say), I do have permission to run that script.
However, when I run this mind numbingly simple script (above), I get the response:
scriptname: No such file or directory
What am I missing?! the commands work as expected when entered at the CLI, so I am at a loss to explain the error message. How do I fix this?
Looking at your script makes me think that the script you want to launch a script which is locate in the initial directory. Since you change you directory before executing it won't work.
I suggest the following modified script:
#!/bin/bash
SCRIPT_DIR=$PWD
cd /path/to/a/folder
$SCRIPT_DIR/scriptname
cd /path/to/a/folder
pwd
ls
./scriptname
which'll show you what it thinks it's doing.
I usually have something like this in my useful script directory:
#!/bin/bash
# Provide usage information if not arguments were supplied
if [[ "$#" -le 0 ]]; then
echo "Usage: $0 <executable> [<argument>...]" >&2
exit 1
fi
# Get the executable by removing the last slash and anything before it
X="${1##*/}"
# Get the directory by removing the executable name
D="${1%$X}"
# Check if the directory exists
if [[ -d "$D" ]]; then
# If it does, cd into it
cd "$D"
else
if [[ "$D" ]]; then
# Complain if a directory was specified, but does not exist
echo "Directory '$D' does not exist" >&2
exit 1
fi
fi
# Check if the executable is, well, executable
if [[ -x "$X" ]]; then
# Run the executable in its directory with the supplied arguments
exec ./"$X" "${#:2}"
else
# Complain if the executable is not a valid
echo "Executable '$X' does not exist in '$D'" >&2
exit 1
fi
Usage:
$ cdexec
Usage: /home/archon/bin/cdexec <executable> [<argument>...]
$ cdexec /bin/ls ls
ls
$ cdexec /bin/xxx/ls ls
Directory '/bin/xxx/' does not exist
$ cdexec /ls ls
Executable 'ls' does not exist in '/'
One source of such error messages under those conditions is a broken symlink.
However, you say the script works when run from the command line. I would also check to see whether the directory is a symlink that's doing something other than what you expect.
Does it work if you call it in your script with the full path instead of using cd?
#!/bin/bash
/path/to/a/folder/scriptname
What about when called that way from the command line?