I came across $- and found that it is used to determine the flags set for the shell.So I just did an echo $- and it gave me ism . Now i is for interactive shell, m is for monitor mode but I dont know what s means.
Moreover I have sample script test.sh as below
#!/bin/ksh
echo "Hi I am shell and I am about to figure out the flags set for me :-)"
echo $-
When I execute the script like this-- ./test.sh I am getting the flag as h but upon executing sh -x test.sh
I am getting xh . I think this x is coming from sh -x but I am not sure how and why.
I tried to google reagrding the flags but found nothing (maybe because my seach keyword is not proper).
Any information on this will be helpful.Thanks in advance :-)
You are using Korn shell in your script, are you using that interactively as well?
man ksh
is your friend.
- Options supplied to the shell on invocation or by the set
command.
Search for Invocation, the correct term for these settings is options (not flags).
So yes, the x is from the set -x. This is a shortcut for set -o xtrace. To see all those options, and their current settings, set -o (note that only a few have single character shortcuts). Try
set --man
on the command-line (if you have a very old version of ksh, that won't work).
-s just means that commands come from stdin.
Related
I have copied a shell script and it is pretty much simple but on the first line with shebang, the -xe flag is specified.
#!/bin/bash -xe
Can anyone explain what does it do? I have searched but could not find any helping material.
This is adding shell options to the shebang:
-x, -o xtrace: Trace display executed statements.
-e, -o errexit: Exit on error, but inconsistently for legacy POSIX compliance.
#!/bin/bash -xe
This shebang setting combines two discouraged bad practices with their own set of issues:
First bad practice is setting shell options in the shebang; because it means they will be ignored when invoking the script directly with: bash script_name, rather than making the script file executable, and invoking ./script_name.
Options shall be set explicitly in code with set -x, or preferably use their more straightforward long name (example: set -o xtrace instead of set -x).
Second bad practice is using the -e option or set -o errexit which is only there for legacy POSIX compliance, but acts so inconsistently in different situations; that it causes more bugs than it avoids.
Here are some references about those set -e, set -o errexit quirks and issues:
BashPitfalls § 60.1. errexit - Greg Wooledge
Why doesn't sh with errexit work with a command list? - Stack Overflow
Yes. I know I shouldn't be using it for scripting. Yes. It is rubbish. I am indeed a fool.
Nevertheless.
I'd like to see the commands the script is executing, for debugging purposes. I think you get this effect with set -x or set -v in bash scripts.
So e.g., if the script were
#!/bin/tcsh
echo "Hello"
then when it ran, I'd see
echo "Hello"
Hello
Put:
set echo
and/or
set verbose
at the top of your script. That will print out everything that happens in your script and are equivalent to the bash set -x and set -v commands.
Lets say your script name is tcsh_file
Lets assume this file includes shebang as well.
now run this command on terminal
tcsh -x tcsh_file
this will print every line before executing it. it's basically an interactive mode of execution.
Is this what you needed?
I am trying to create an AppleScript with commands below. An issue I am having is there is an error at the third line. I have no problem using the lame command in the terminal directly. In addition, lame is not a native Mac utility; I installed it on my own. Does anybody have a solution?
do shell script "cd ~/Downloads"
do shell script "say -f ~/Downloads/RE.txt -o ~/Downloads/recording.aiff"
do shell script "lame -m m ~/Downloads/recording.aiff ~/Downloads/recording.mp3"
-- error "sh: lame: command not found" number 127
do shell script "rm recording.aiff RE.txt"
To complement Paul R's helpful answer:
The thing to note is that do shell script - regrettably - does NOT see the same $PATH as shells created by Terminal.app - a notable absence is /usr/local/bin.
On my OS X 10.9.3 system, running do shell script "echo $PATH" yields merely:
/usr/bin:/bin:/usr/sbin:/sbin
There are various ways around this:
Use the full path to executables, as in Paul's solution.
Manually prepend/append /usr/local/bin, where many non-system executables live, to the $PATH - worth considering if you invoke multiple executables in a single do shell script command; e.g.:
do shell script "export PATH=\"/usr/local/bin:$PATH\"
cd ~/Downloads
say -f ~/Downloads/RE.txt -o ~/Downloads/recording.aiff
lame -m m ~/Downloads/recording.aiff ~/Downloads/recording.mp3
rm recording.aiff RE.txt"
Note how the above use a single do shell script command with multiple commands in a single string - commands can be separated by newlines or, if on the same line, with ;.
This is more efficient than multiple invocations, though adding error handling both inside the script code and around the do shell script command is advisable.
To get the same $PATH that interactive shells see (except additions made in your bash profile), you can invoke eval $(/usr/libexec/path_helper -s); as the first statement in your command string.
Other important considerations with do shell script:
bash is invoked as sh, which results in changes in behavior, most notably:
process substitution (<(...)) is not available
echo by default accepts no options and interprets escape sequences such as \n.
other, subtle changes in behavior; see http://www.gnu.org/software/bash/manual/html_node/Bash-POSIX-Mode.html
You could address these issues manually by prepending shopt -uo posix; shopt -u xpg_echo; to your command string.
The locale is set to the generic "C" locale instead of to your system's; to fix that, manually prepend export LANG='" & user locale of (system info) & ".UTF-8' to your command string.
No startup files (profiles) are read; this is not surprising, because the shell created is a noninteractive (non-login) shell, but sometimes it's handy to load one's profile by manually by prepending . ~/.bash_profile to the command string; note, however, that this makes your AppleScript less portable.
do shell script command reference: http://developer.apple.com/library/mac/#technotes/tn2065/_index.html
Probably a PATH problem - use the full path for lame, e.g.
do shell script "/usr/local/bin/lame -m m ~/Downloads/recording.aiff ~/Downloads/recording.mp3"
I have been struggling to get the path of an installed BASH command via Applescript for a long time. Using the information here, I finally succeeded.
tell me to set sox_path to (do shell script "eval $(/usr/libexec/path_helper -s); which sox")
Thanks.
Url:http://sourceforge.net/project/showfiles.php?group_id=290&package_id=309
./configure
make install
I've recently switched to the ksh93 shell. I did this by adding the following two lines to my .profile file
export SHELL=/usr/local/bin/ksh93
exec $SHELL
Since I did that some simple scripts have started misbehaving in a way I don't understand. I narrowed it down to the following simple script called say test.sh
#!/bin/ksh
echo $0 $1
If I type the command test.sh fred I would expect to see the same output test.sh fred. Instead I see test.sh noglob. If I remove the shebang or if I change it to read #!/usr/local/bin/ksh93 then the script works as expected.
Can anyone explain what's going on, or what to do about it? I'm stumped.
I'm using Solaris 5.9 if it makes any difference.
I notice from the comments that your .kshrc has a set noglob. The set command with no options will set the command-line parameters, which is why $1 is "noglob", it should be set -o noglob.
By the way, setting noglob is weird, are you sure you want that?
I suspect (as others have mentioned) that /bin/ksh is Korn shell 88.
There is an important difference between ksh88 and ksh93 with regards to .kshrc. On ksh88 .kshrc is executed for every korn shell process, even non-interactive ones (scripts). In ksh93 .kshrc is not executed for shell scripts, only for interactive login shells.
When you do exec $SHELL that is not a login shell, it is better to change your entry in /etc/passwd. By the way, using variable SHELL is a bad idea, since that is set by the login shell.
There's probably an alias on ksh in your system with noglob set as an option, or noglob is being passed as a default parameter by default in your old shell. You should also check what ksh you're really calling (check if there's a link to another shell in from /bin/ksh). ksh --version should give some insight as well.
As a last point, instead of calling the shell directly i'd recommend to use
#!/usr/bin/env ksh
Can anyone tell me what are login shell and interactive shell and which configurations each of them read(etc/profile, etc/bashrc, .bash_profile ...)??
I saw some explanation like this:
A login shell is one whose first character of argument zero is a -, or
one started with the --login option.
An interactive shell is one started without non-option arguments and
without the -c option whose standard input and error are both connected
to terminals (as determined by isatty(3)), or one started with the -i
option. PS1 is set and $- includes i if bash is interactive, allowing
a shell script or a startup file to test this state.
But this confused more !!!
The man bash command on your system (INVOCATION section) talks about all of this and it describes which files are read when.
Well, if you don't trust the manual page, try using strace.
strace -o/tmp/tr -f bash
exit
grep open /tmp/tr | grep $HOME
For me, this shows:
18316 open("/home/sethrobertson/.bashrc", O_RDONLY) = 3
What does it show for you?