"here documents" and /tmp

Hi folks,

I am developer on solaris 8, I am using "here documents <<eof" but unfortunately I am having contention problems with /tmp directory because this facility tries to create a temporary file sh99999 on it but this filename already has been created by a different process before.

To avoid this I had thought on using $TMPDIR variable, but it seems that it only has effect with compilers.

I wonder how I can redirect /tmp directory to another directory only during the execution of my shell script in order to avoid this problem.

Thanks in advance
jterra

I think that the filename is supposed to contain the pid of the shell and this should prevent name collisions. Could these be old filenames from shells that aborted? If so the fix is to address the condition(s) causing the aborts. Another though is to periodically clean out the old files. If neither is possible, crucial scripts can be written to not use here-docs.

:frowning: Hello Perderabo,
First of all, thanks for your interest.
Yes, you are right, the filename consists of �sh� + pid, and the old filenames correspond to aborted process from operating system because they have as owner �root�. My system administrator has told me that these old files only will be removed at reboot time, but the machine only is rebooted fortnightly. And me as developer I only can try to avoid to allocate sh files on /tmp directory. I also have thought of using real files, but I have a lot of code using here-documents with variables, and before taking that way I would like to know if it were possible to redirect /tmp directory doing the same than compilers.
jterra

#!/bin/ksh

............

typeset -i u="${$}"

# keep incrementing "u" till you find a non-existant tmp file
while :
do
   tmpFile="/tmp/sh${u}"
   if [ ! -f "${tmpFile}" ] ; then break; fi
   ((u = u + 1 ))
done

command <<EOF >> "${tmpFile}"
.........
.........
EOF

Hello vgersh99,
This is very interesting, but using here-documents I think that sh+pid file is allocated on /tmp automatically, so when system finds <<EOF the automatic allocation is done although later you redirect the output using >> "${tmpFile}". So the problem remains.
jterra

I don't understand.
You have a 'here-doc' that you redirect the output to a temp file. Right?
And that temp might exist with missing 'w' permissions for you to write to. Right?

If that's the case what I'm suggesting is to find a temp file that does not exist. Take a value of '$$' - see if the tempFile exists. If it doesn't - use that file for redirection.
If it does, keep incrementing '$$' till you find the file that does not exist.

Am I missing something obvious here?
It might help if you posted relative parts of your script.

vgersh99's code is not helpful. The shell itself decides on which name to use for here-docs. I suppose that you could keep forking shells until you finally get one with a pid that is not compromised with /tmp/sh* aritifacts, but that really is not a great solution. The answer to the original question is no, /tmp/sh* is hard coded. Your sysadmin's attitude is unfortunate. Had he been willing, this problem could be solved with a clever script to reap the old tmp files. This leaves the option of rewriting the scripts to avoid here-docs.

I think I misunderstood the OP - I thought of output redirecting and NOT about the here-doc itself.
My apologies.

Yes, I have a here-doc, but I do not redirect nothing to /tmp, it is done by operating system (os) automatically. So, if the filename assigned already exist on /tmp the os aborts my shell script. Your script would be great if I controlled the redirection, but it is driven by os. See below an extract from my shell script with a here-doc calling to sqlplus.

while [ 0 ] ; do

   \#-- check if cyclic process must be stopped

   if [ -f $gp05000o_stop ] ; then
      Flog "STOP RUNNING - $gp05000o_stop"
      Fdelete\_temp_files
      Fexit
   fi

   \#-- get the request from the users from the database

   sqlplus -S $GMEP\_USU/$GMEP_PWD &lt;&lt; \\

_eof_sqlplus > /dev/null

   set termout      off
   set serveroutput off
   set heading      off
   set linesize     400
   whenever sqlerror exit 1 rollback

   spool $gp05000o\_process\_to_run

   select 'gp05000o','@', command, '@', rowid, '@', process_number, '@'
     from oproc_call
    where process_id   = '$process_id'
      and proc_status  = '$process_wait'
      and rownum       = 1;

   spool off

   exit

_eof_sqlplus

 . . .

 done

=====================
error message reached

/disk1/gmeasp/code/sh/gp05000o.ksh[202]: /tmp/sh23628.13: cannot create

:wink: My god!! Before rewriting the code, I will try to convince my sysadmin one more time to develop a easy shell script to remove old sh* files from /tmp, I do not think that it takes more than one line.
Thanks to all for your valuable help
This is my first contact in this forum, and it has been excellent
jterra

....before you do this.....
Cannot you simply avoid using here-doc as previously suggested?
I see you're using ORACLE sqlplus. You can save your sql statements in a temp file [using your OWN derivation rules] and simply pass it sqlplaus on the command line. [and remove the temp file afterwards].

I don't Oracle at my hands now, but it should be pretty easy.

Yes, I could do it, but as you can see there are variables. And using here-doc the substitution is done by os automatically. However using my own file, first the sentences would be an additional component out of script, the substitution should be done manually using sed for instance, and ... I have a lot of code using here-doc. Any way, thanks for your suggestion.

something like this should get you started:

typeset -i u="${$}"

# keep incrementing "u" till you find a non-existant tmp file
while :
do
   tmpFile="/tmp/sh${u}"
   if [ ! -f "${tmpFile}" ] ; then break; fi
   ((u = u + 1 ))
done

cat "
set termout off
set serveroutput off
set heading off
set linesize 400
whenever sqlerror exit 1 rollback

spool $gp05000o_process_to_run

select 'gp05000o','@', command, '@', rowid, '@', process_number, '@'
from oproc_call
where process_id = '$process_id'
and proc_status = '$process_wait'
and rownum = 1;

spool off

exit
" > "${tmpFile}"

sqlplus -S $GMEP_USU/$GMEP_PWD < "${tmpFile}"
....
/bin/rm "${tmpFile}"

Just do something like...

filename=/tmp/jhjHkkkGRrqxbmXppoujuuyttrjfeJgfgg$$
echo "this
that
the other
last line" > $filename
program < $filename
rm $filename

*dang* vgersh99 beat me to it... I gotta type faster... :smiley:

your variables will be expanded by the surrounding shell.
this is simply a work-around your sysadmins and another way of feeding the commands.

I think vgersh99 has a typo... that
cat "
needs to be
echo "
or something....

and note - no UUOC this time.

you're right - I'm so used to using here-docs for 'cat' for multi-line output... but that would defeat the purpose here.

thanks.

:slight_smile: Huummm!! I am jumping of happiness. I am impressed with this easy solution.
Really, thanks a lot to both.
jterra