Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keep a file open forever within a bash script

Tags:

bash

I need a way to make a process keep a certain file open forever. Here's an example of what I have so far:

sleep 1000 > myfile &

It works for a thousand seconds, but really don't want to make some complicated sleep/loop statement. This post suggested that cat is the same thing as sleep for infinite. So I tried this:

cat > myfile &

It almost looks like a mistake doesn't it? It seemed to work from the command line, but in a script the file connection did not stay open. Any other ideas?

like image 495
User1 Avatar asked Aug 11 '10 19:08

User1


People also ask

What is $@ in Bash script?

bash [filename] runs the commands saved in a file. $@ refers to all of a shell script's command-line arguments. $1 , $2 , etc., refer to the first command-line argument, the second command-line argument, etc. Place variables in quotes if the values might have spaces in them.

How do you write an infinite loop in shell script?

The following syntax is used for create infinite while loop in a shell script. echo "Press [CTRL+C] to exit this loop..." You can also Unix true command with while loop to run it endlessly. The while loop syntax with true command will look like below example.

What is sleep Infinity command?

Linux command — `$ sleep infinity` is for forever sleeping ( never awake until escape )


2 Answers

Rather than using a background process, you can also just use bash to open one of its file descriptors:

exec 5>myfile 

(The special use of exec here allows changing the current file descriptor redirections - see man bash for details). This will open file descriptor 5 to "myfile" (use >> if you don't want to empty the file).

You can later close the file again with:

exec 5>&-

(One possible downside of this is that the FD gets inherited by every program that the shell runs in the meantime. Mostly this is harmless - e.g. your greps and seds will generally ignore the extra FD - but it could be annoying in some cases, especially if you spawn any processes that stay around (because they will then keep the FD open).

Note: If you are using a newer version of bash (>4.1) you can use a slightly different syntax:

exec {fd}>myfile

This allocates a new file descriptor, and puts it in the variable fd. This can help ensure that scripts don't accidentally overwrite each other's file descriptors. To close the file later, use

exec {fd}>&-
like image 184
psmears Avatar answered Oct 04 '22 05:10

psmears


On the cat > myfile & issue running in terminal vs not running as part of a script: In a non-interactive shell the stdin of a backgrounded command & gets implicitly redirected from /dev/null.

So, cat > myfile & in a script actually gets translated into cat </dev/null > myfile, which terminates cat immediately.

See the POSIX standard on the Shell Command Language & Asynchronous Lists:

The standard input for an asynchronous list, before any explicit redirections are 
performed, shall be considered to be assigned to a file that has the same 
properties as /dev/null. If it is an interactive shell, this need not happen. 
In all cases, explicit redirection of standard input shall override this activity.

# some tests
sh -c 'sleep 10 & lsof -p ${!}'
sh -c 'sleep 10 0<&0 & lsof -p ${!}'
sh -ic 'sleep 10 & lsof -p ${!}'


# in a script
-  cat > myfile &
+  cat 0<&0 > myfile &
like image 35
ralfw Avatar answered Oct 04 '22 05:10

ralfw