Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I wonder if there is a way to create a 'virtual file' from a bash output.

Example:
Let's say I want to email the output of mysqldump as an attachment to an external email address.
I can use mutt to do so.
The mutt option I need to use is '-a '.
I know I could use a temporary file (mysqldump mysqldumpoptions > /tmp/tempfile && mutt -a /tmp/tempfile admin@example.org ...), but I would rather redirect the mysqldump output directly to mutt instead.
Mutt's -a option only accepts a file and not a stream, but maybe there is a way to pass it some kind of virtual file descriptor or something along those lines.
(something like mutt -a $(mysqldump mysqldumpoptions) admin@example.org)

Is it possible? If not, why?

This is maybe a silly example and there surely are easier ways to do this, but I hope it explains my question about creating a virtual file from the output of another command.

share|improve this question
    
I couldn't get <() to work until I realized I was using sh instead of bash. It is working great. I will upvote the helpful responses when (if) I reach the minimum needed reputation. Thank you for all the responses. –  Pierre Jul 14 '09 at 17:05
add comment

7 Answers

up vote 19 down vote accepted

This is the cleanest way to do what you want:

mutt -a <(mysqldump mysqldumpoptions) admin@example.org

The <() operator is what you were asking for; it creates a FIFO (or /dev/fd) and forks a process and connects stdout to the FIFO. >() does the same, except connects stdin to the FIFO instead. In other words, it does all the mknod stuff for you behind the scenes; or on a modern OS, does it in an even better way.

Except, of course, that doesn't work with mutt, it says:

/dev/fd/63: unable to attach file.

I suspect the problem is that mutt is trying to seek in the file, which you can't do on a pipe of any sort. The seeking is probably something like scanning the file to figure out what MIME type it is and what encodings might work (ie, whether the file is 7bit or 8bit), and then seeking to the beginning of the file to actually encode it into the message.

share|improve this answer
2  
Awesome! I am seeing such redirection for first time. –  Saurabh Barjatiya Jul 14 '09 at 11:12
    
Thank you for the good explanation! I have never seen this before, in any tutorials on I/O redirection. –  Christian Mann Jul 21 '11 at 18:18
add comment

A FIFO is probably the best way. However you can use mkfifo /path/to/fifo instead

share|improve this answer
add comment

Mutt -a option specifically uses MIME types defined at /etc/mime.types. None of the virtual file types that you would think are actually a valid mime type registered, so I don't think mutt attachment would work. Just for the proof of the concept, you can try install mime-support package (which provides mime file access binaries such as see, edit, etc) and run see against a virtual file (say a pipe), you will see that it does not recognize it. The fundamental issue is that normally a virtual file holds data content in memory, not on disk, the file object is just a pointer. You can even try wrap a virtual file with tar/gz and make mutt happy but I doubt you will get anything useful out of the other end... :)

share|improve this answer
add comment

i may be missing something here, but why use mutt when this sounds more like a job for /usr/sbin/sendmail (or wherever it lives on your distro)?

mysqldump mysqldumpoptions | sendmail admin@example.org

most unix MTAs provide a /usr/sbin/sendmail command, and they all understand more-or-less the same options and work in more-or-less the same way. in almost all cases, you don't need to care which particular MTA/implementation of sendmail you're using.

there are several other alternatives too, including mail/mailx

share|improve this answer
    
then it's not an attachment, which seems likely to be harder to use for the recipient –  freiheit Jul 14 '09 at 7:06
1  
in that case, a better solution would be to use a tool like metamail(1) or mime-construct(1p) or writing your own using something like the perl MIME::Lite module (my personal favourite because it makes it easy to do the most common mime-related things). –  cas Jul 14 '09 at 9:49
add comment

You may be able to use the filename /dev/stdin with mutt, which will read from its stdin.

mysqldump mysqldumpoptions | mutt -a /dev/stdin admin@example.org

Hm, I just tried this and mutt complains:

/dev/stdin isn't a regular file.
/dev/stdin: unable to attach file.

Oh well. I think this answers your question though, with the -a option mutt expects a regular file, which implies not a device or pipe.

share|improve this answer
add comment

Does it need to be an attachment? If it can appear as the body of a message (7-bit clean ascii, doesn't contain '.' on a line by itself, etc.), then something like this would work:

mysqldump mysqldumpoptions | mutt -s "today's mysql dump" admin@example.org

share|improve this answer
add comment

I think what you are looking for is a fifo using mknod

mknod /tmp/foo p

echo hello > /tmp/foo &

cat /tmp/foo

Note the writing process will block if there is not a reading process.

e.g

mknod /tmp/foo p

mysqldump mysqldumpoptions > /tmp/foo &

mutt -a /tmp/foo

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.