Running in the Background

Share Button

We all have that list of features we just wish Oracle would adopt in their latest version: alterable redo log files, command history in SQL*Plus, DBA_OOPS package with various rollback options when you screw something up…

One of my biggest wishlist items is detachable sessions. In Oracle 10g we got the Datapump tool for exports and imports. One of its best features is the ability to detach from a running export or import and re-attach as needed. When you kick off an import (impdp) you can press CTRL+C and drop out to a client. From there, you can type ‘exit_client’ and detach completely, allowing you to go home, get a coffee, turn off your computer, or otherwise amuse yourself in whatever way seems best. For example:

bash-3.00$ expdp system/******** directory=dpexp full=y dumpfile=test.dmp

Export: Release 11.2.0.3.0 - Production on Mon Jun 17 07:27:50 2013

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Starting "SYSTEM"."SYS_EXPORT_FULL_02":  system/******** directory=dpexp full=y dumpfile=test.dmp 
Estimate in progress using BLOCKS method...
Processing object type DATABASE_EXPORT/SCHEMA/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 52.70 GB
^C
Export> exit_client

bash-3.00$ 

As you can see, pressing CTRL+C allowed me to exit the client back to a bash prompt. Since the task is owned by the job SYS_EXPORT_FULL_02, it stays running in the background. However, I can re-attach to the job and use continue_client to keep watching, or:

bash-3.00$ expdp system/******** attach
...
Export> kill_job
Are you sure you wish to stop this job ([yes]/no): yes

bash-3.00$ 

And there it is. But the important thing to note is that when I kick off an export or import with expdp and impdp, it always runs as a job. That means that your foreground process is only attaching to the background process running the job; this is what allows you to attach and detach at will.

At the same time, that is technically always the case. When you connect to the database in SQL*Plus and run a command, your SQL*Plus process is not the one performing the work; instead, the commands are run against the DB with your server process–LOCAL=NO owned by init for remote connections, or LOCAL=YES owned by your SQL*Plus process for non-remote connections. It would be very nice to be able to detach and re-attach to tasks run from any Oracle client.

That being said, it’s not possible. So here are some ways to run your work in the background that are useful for cases where you have a long running process and aren’t sure if you can wait around for it to complete.

NOHUP + Background

Most everyone knows NOHUP (No Hangup). It is a command run from the UNIX/Linux prompt in which you call your script, usually with a ‘&’ sign at the end signifying you want the work to occur in the background, like so:

steve@220883 backgrounder]$ nohup ./longrun.sh &
[1] 6446
[steve@220883 backgrounder]$ nohup: appending output to `nohup.out'

[steve@220883 backgrounder]$ 

You can still keep an eye on your job with the ‘jobs’ command, and even kill the job if need be:

[steve@220883 backgrounder]$ jobs
[1]+  Running                 nohup ./longrun.sh &
[steve@220883 backgrounder]$ kill %1
[1]+  Terminated              nohup ./longrun.sh
[steve@220883 backgrounder]$ 

Running a command with ‘nohup’ is a great way to kick something off in the background, allowing you to disconnect and do other things.

Disown

But what if you forgot to run the nohup command? You can still kick your program to the background with CTRL+Z and run it in the background; however, you still own it:

[steve@220883 backgrounder]$ ./longrun.sh
[1]+  Stopped                 ./longrun.sh
steve@220883 backgrounder]$ bg
[1]+ ./longrun.sh &

Notice that pressing CTRL+Z stopped the job, and typing ‘bg’ ran it in the background (signified by the ‘&’ sign). However, without NOHUP the command is still owned by my session. If I exit right now it will hang and the fate of my background job will be unclear.

To get around this problem, you can use the ‘disown’ command:

[steve@220883 backgrounder]$ disown
[steve@220883 backgrounder]$ 

Nothing special happens in the foreground. But in the background, your job is now owned by init (PID 1). You can feel free to exit and go about your business.

Special Note: There is a special place in Hell for those who CTRL+Z out of ‘vi’.

Screen

Shamelessly borrowed from 5 Quick and Dirty Linux Tips You May Not Know

This one was a godsend. Have you ever been working on a long running operation and you lost your connection to Oracle, or had to go home, or god knows what else? It is a horrible pain and one that really messes up a lot if it gets you at the wrong time. That should be a thing of the past if you use screen.

Screen is a multiplexed terminal, allowing you to spawn multiple terminals in a single terminal session. Opening a new ‘screen’ is simple; simply type the word screen at a Linux command line:

[skaram@server2 ~]$ echo HELLO!
HELLO!
[skaram@server2 ~]$ screen

Notice your terminal clears and you start at a new prompt. Now I will go ahead and make it wait for input.

[skaram@server2 ~]$ read -p "Press Enter"
Press Enter

If I press CTRL+A, then CTRL+D, my screen will detach, putting me back on the ‘parent’ terminal session:

[skaram@server2 ~]$ 
[skaram@server2 ~]$ 
[skaram@server2 ~]$ echo HELLO!
HELLO!
[skaram@server2 ~]$ screen
[detached]
[skaram@server2 ~]$ 

If I want to get back to the child screen, I can type screen -rx to re-attach. Or start a new terminal with a fresh ‘screen’ command. You can even detach from multiple terminals and connect to the one of your choosing:

[skaram@server2 ~]$ screen -list
There are screens on:
	10913.pts-2.server2	(Detached)
	10883.pts-2.server2	(Detached)
	9700.pts-2.server2	(Detached)
3 Sockets in /var/run/screen/S-skaram.

[skaram@server2 ~]$ screen -rx 10883.pts-2.server2

But wait, there’s more! If you and a buddy, coworker, consultant, engineer, parole officer, etc. want to share the same screen, you can login as the same user via SSH and then both type screen -rx. You will both join the multiplexed session (screen) and be able to type and see what each other is typing. It is awesome for following along, mentoring, etc.

DBMS_SCHEDULER

While Oracle Scheduler is an outstanding tool for running tasks in the future or on a schedule, it can also be used to run tasks right away. The best part is that since it is native to Oracle, it can run a PL/SQL block in addition to a shell script. That means if all you need to do is gather some stats or run a big update, you don’t need to make a shell script wrapper and nohup it. For example:

begin
  dbms_scheduler.create_job('stats_gather_test_uno',
    job_type=>'plsql_block',
    job_action=>'begin
dbms_stats.gather_schema_stats(ownname => ''SCOTT'');
end;',
    enabled=>true);
end;
/

That command will create a job called STATS_GATHER_TEST_UNO that gathers stats on the SCOTT schema right away in the background. You can use DBA_SCHEDULER_RUNNING_JOBS and other views to get more info on its progress. If you want to run a shell script, then job_type should be set to ‘EXECUTABLE’ and job_action will be the script itself.

Note: There are two single quotes around SCOTT in that example, as we are using single quotes inside of single quotes. If you need to run something like ‘execute immediate’ you will have to use even more quotes, for example:

'begin
execute immediate ''something with ''''quotes'''''';
end;'

Ouch. You can get around this problem with q-quotes, introduced in 10gR1.

Conclusion

These options are a far cry from a real backgrounding capability for Oracle sessions. It would be great if we could do something like DBMS_SESS.DETACH(sid=>123, jobname=>’way_too_long’) then re-attach as needed. But until that day, there are some viable options as long as you show a little forethought.

You may have noticed that ‘cron’ didn’t make the cut. We all know and love the cron tool for scheduling something that we don’t want running in our terminals; however, it’s already a very commonly blogged-about tool and somewhat inadequate for our “just run it once in the background please, thanks” requirements.

Share Button

2 comments

  1. Steve – excellent tips on commands that
    Should be in everyone’s toolkit. Keep up the
    Good work

  2. Nice one Steve, I had not known about the screen -x option (note to self: reread man pages…)
    A couple of things worth noting: if one user exits the screen with CTL-D, then it exits for all – should be obvious I know, but it was only obvious to me after the fact 🙂

    Another screen trick: attempting to start screen when your terminal device does not allow it:

    [jkstill ~]$ screen -rx 6979.jkstill
    Cannot open your terminal ‘/dev/pts/9’ – please check.

    Use the script command to start a new pty and run screen:

    [jkstill ~]$ script -c ‘screen -rx 6979.jkstill’ /dev/null
    Script started, file is /dev/null

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.