SQLplus script from file with bash substitutions - bash

I am running a bash script that includes a here document, which calls SQLPLUS. This includes a .sql script to perform several grants. It works correctly without the substitution.
I want to be able to substitute in a bash variable into the grant statements. Is that possible?
This is a snippet from the bash script
CREDLINE=ownusr/ownpass
GRANT2DO=foo.sql
PASSPROC=bar <=== this is what I want to pass
sqlplus << EOQ11
$CREDLINE#chaos01
#$GRANT2DO
quit
EOQ11
This is a snippet from the foo.sql
grant execute on $PASSPROC to user86;
grant execute on $PASSPROC to user99;
I have tried several variations on $VAR and &1, but none has worked so far.

You have to call the sql-script with the value of what you want to pass
from sqlplus execute the script:
#foo.sql bar
in foo.sql use:
grant execute on &1 to usr

You can make your script create .sql file instead of having it replace existing one. Then pass it to sqlplus like you already do.
To make the script readable, you can use so-called "here documents" syntax, which is described here and which you are seemingly already familiar with.
If you insist on doing actual substitution, you could copy the template .sql to some temporary file and run sed -i on it with proper arguments to replace the variables. That, however, is much more complicated than the approach above.

Related

How to properly do Multiple Command Substitution in bash

I am trying to have a variable execute 2 commands when typed in the terminal, namely change to a specific directory and run an executable. However when executed it returns
bash: cd: too many arguments
This is how I defined the variable in .bashrc
export FOO='cd "/path/to/directory" ; /path/to/executable'
When I input this line directly it works fine. So what is the proper way of defining such a variable?
After the suggestion by Barmer and Gordon and a quick search I managed to achieve the result I wanted using functions.

getting permission to execute a bash script

im trying to get my server to execute a simple bash script:
#!/bin/bash
echo Hello World
After saving this to /var/www/script (im saving it to the web directory for no reason in particular) i try and execute it with
exec /var/www/script
This fails returning i don't have permission to execute it, sudo exec isn't a thing so i do sudo -i then run exec /var/www/script as root and i still have permission denied. I fairly uncertain why executing it as root doesn't work. Im wondering if i'm
A) using the wrong command to execute a bash script
B) have incorrect formatting in the script
C) shouldn't have saved it to /var/www/
D) done some other thing that i'm not even aware of.
Im running ubuntu server 16.04 if that helps.
File Permissions
First, make sure that you have the correct file permissions:
chmod +x /var/www/script_name #Gives the current user execute permissions
Executing Your Bash Script
In order to execute your bash script, the easiest option is to just simply call it (without any additional commands) by typing in the relative path to the script:
/var/www/script_name
There are other options for explicitly executing your script from the shell (in your case, use the bash shell to execute your script as a bash script). From TLDP documentation...
A script can also explicitly be executed by a given shell, but generally we only do this if we want to obtain special behavior, such as checking if the script works with another shell or printing traces for debugging:
rbash script_name.sh # Execute using the restricted bash shell
sh script_name.sh # Execute using the sh shell
bash -x script_name.sh # Execute using the bash shell
A Note on File Extensions: "Shebang" line > File extension
It is not an advised practice to use file extensions with your scripts, especially if you think your code may evolve beyond its current functionality.
Just in case you were wondering if the file extension may be your problem... it is not. It is important that you know that the file extension of a script isn't necessary at all. What matter is what you put in the "shebang" line:
To use the sh shell:
#!/bin/sh
To use the bash shell:
#!/bin/bash
It won't matter what file extension you use - the "shebang" line indicates what shell will be used to execute the script. You could save a script with the "shebang" of #!/bin/bash as script_name.py, but it would remain a bash script. If you attempt to execute it, ./script_name.py, it would be executed as a bash script.
As #Arjan mentioned in the comments, using file extensions for your script could lead to unnecessary complications if you decide to change the implementation of your project (i.e., a different shell / language):
I could decide later to shift my project to sh, python, perl, C, etc. Perhaps because I want to add functionality. Perhaps because I want to make it portable to a system without bash. It would be much more difficult if I used the .sh file extension, since then I'd need to change all my references to the script just because I changed its implementation.
You have two choices:
Run it as an argument to bash:
bash /var/www/script
Alternatively, set the execute bit:
chmod +x /var/www/script
And, now you can execute it directly:
/var/www/script

Can SQL*Plus read environment variables from the machine is it running on?

I'm aware that the database engine itself is (often) on another machine and that SQL*Plus has no direct way of reading those environment variables, but I'm in a tricky situation where I merely need the environment variables from the machine the client itself is running on.
Is there a way to cheat these values into the SQL*Plus client from within a single script that will be run in SQL*Plus? The script consists of a single begin/end PL/SQL block, but if I need to use SQL*Plus directives of the set/define/variable sort that shouldn't be a problem either.
What I can't do is alter the way that the SQL*Plus executable itself is started (I don't have access to pass the values in as arguments).
Is there any way to accomplish this?
Note: dbms_system.get_env() seems to retrieve environment variables from the server itself, which is what I do not want.
You can get a few client-related things from the USERENV context, but not arbitrary environment variables.
If you can create a file on your local machine you could use the host command to set a substitution variable based on an environment variable:
SQL > host echo define homedir=$HOME > /tmp/gethome.sql
SQL > #/tmp/gethome.sql
SQL > host rm -f /tmp/gethome.sql
SQL > select '&homedir.' as home from dual;
HOME
------------
/home/apoole
1 row selected.
Not very pretty, but if you can't pass the variables on the command line as positional parameters then your options are rather limited.
This is using a Unix-y paths and commands of course, but you can do the same sort of thing in Windows.
Sys_context should solve your problem. You can set custom environment variable in database using DBMS_SESSION.SET_CONTEXT ('MY_NAMESPACE', 'MY_PARAMETER', v_input_parameter); and then fetch it using SYS_CONTEXT ('MY_NAMESPACE', 'MY_PARAMETER');
So you can run a initial pl/sql block to set variable in session and then use it as per requirement.
You can see an example here: http://blog.contractoracle.com/2010/03/using-dbmssessionsetcontext-to-store.html
If you could pass the variable via sqlplus argument passing mechanism. you could do the following,
cat > myscript.sql <<!
select '&1' as HOME from DUAL;
!
sqlplus user/pwd#db #myscript.sql $HOME

Chef bash resource, command attribute doesn't work

I have a simple recipe that looks like this:
bash "create folder" do
command "mkdir -p /home/user/folder"
not_if {::File.directory?("/home/user/folder")}
end
It doesn't work. It says that it's executing, but it doesn't create the folder. If I change bash to execute then it works. If I change command to code then it works. But the bash and execute docs have literally the same specs on command.
Am I doing something wrong or are the docs wrong?
To quote the attributes documentation of the Bash resource:
code: A quoted (” ”) string of code to be executed.
command: The name of the command to be executed. Default value: the name of the resource block (see Syntax section above).
This, the command attribute is just the name of the command, not the full code to run. With the bash resource (and all the other script resources), you should use the code attribute to send the code to be executed.
The correct resource definition is thus:
bash "create folder" do
code "mkdir -p /home/user/folder"
not_if {::File.directory?("/home/user/folder")}
end
In fact, the contents of the command attribute is not used there anywhere, it's just there because the script resource inherits from the execute resource and thus inherits all its possible attributes.
As a final remark, to create a directory, you should use the actual idiomatic directory resource built-in to Chef instead of a bash script like this:
directory "/home/user/folder" do
recursive true
end
The default behavior of bash is Use to run a script.
The default behavior of execute is Use to run a command.
You are running a command, not a script, so it makes sense you should be using a code block or using execute instead. The difference between the two is... not well defined in the docs. I have found at least 3 or 4 examples in the docs that were outright wrong and submitted corrections, some of which still haven't been made.

Executing oracle queries in Shell Script

Please tell me how can i excute an oralce query inside a shell script.I am writing a shell script where I need to execute the oracle queries and scripts inside the shell script.
What is the purpose of these lines
sql_file=sachin.sql
cat <<!SQL > $sql_file
select $1 from dual;
exit;
!SQL
I think they are creating a new file, but what exactly is !SQL
It is the multi-line string terminator (a here-doc). There is no special meaning to the letters used, you could just as well have written !ORACLE, it just denotes that the content of the multi-line string are SQL commands.
What your script does is create a text file called sachin.sql with the contents specified between the two !SQL tokens.
PS: Not sure what shell this is for, my bash does not like the exclamation mark, thinks it is an event.
!SQL is just a token to notify the end of sql statements (here-doc) we can use any token like EOF, ENDSQL anything.
but the pre-requisite is the second token !SQL should start on the first column of the line.

Resources