Ask Ubuntu is a question and answer site for Ubuntu users and developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

So, here i am, playing with some bash scripts, and there is something that doesn't work:

#!/bin/bash

script -c \
sudo apt-get update &&
sudo apt-get upgrade &&

exit

echo "(Not important for the question)"

I want to run the usual update and upgrade stuff, and also record the output, but when i run the script, it only says that the script started to record in apt-get, shows the usage of sudo ( usage: sudo -h is the first line ), and says that the sript is done. After that it starts the sudo stuff.

What do i need to do in order to record the output of the update&upgrade task? In general, how can i record the output of an entire shell script?

share|improve this question
up vote 9 down vote accepted

If I understand your question correctly, you can use the following:

#!/bin/bash

apt-get update &> update.log
apt-get -y upgrade &> upgrade.log

echo "all done"

Save this script as run_updates.sh, make it executable with chmod 755 run_updates.sh and run it with sudo ./run_updates.sh.
If you want to save all output in one file, remove the &> updates.log and &> upgrades.log from the script and run the script as sudo./run_updates.sh &> run_updates.log


Explanation of the script:

  • apt-get update &> update.log runs apt-get update and saves the output in update.log
  • apt-get -y upgrade &> upgrade.log runs apt-get upgrade and saves the output in upgrade.log. The -y prevents apt from asking to continue (it assumes "yes")

A note on redirections:
You can use the redirections below to "send" output from a command or script to a file.

  • &> redirects STDOUT and STDERR
  • > or 1> redirects STDOUT
  • 2> redirects STDERR

A note on sudo:
This is probably the reason why you got errors. When running a command that needs sudo in a script, it is a good idea to put the command without sudo in the script and run the script with sudo. Otherwise, you would have to give your sudo password to the script in some way, which is bad.


Edit:
In the following code, the output of both apt commands is redirected to update.log. The double > (>>) is used to append data to a file (instead of replacing it)

#!/bin/bash

apt-get update &> update.log
apt-get -y upgrade &>> update.log

echo "all done"
share|improve this answer
    
I didn't realize i could run the script itself as sudo. It'll make my life easier, thanks. About the redirection, is it possible to write something in the script to automatically record the output of both commands into the same file instead of writing the output on separate files? – macacomen98 Feb 14 at 20:10
    
@macacomen98 see my edit ;-) – Wayne_Yux Feb 14 at 22:50
    
Ok, that gets the work done. Thanks :) – macacomen98 Feb 15 at 12:00

In general, to log the output of the entire script, redirect the output of the entire script:

exec &> some.log
# Or, when using `/bin/sh`:
# exec >some.log 2>&1

The exec builtin is often used to change the open file descriptors or add new file descriptors (the sources and destinations of input and output) for the shell.

For example, given example.sh:

#! /bin/bash
exec &> some.log
ls foo
echo foo

On running:

$ ./example.sh
$ cat some.log
ls: foo: No such file or directory
foo

If you want both output to screen and to a file, use tee with process substitution:

exec &> >(tee some.log)
share|improve this answer

No need for a script, just do it in one line using Bash redirections and tee:

{ sudo apt-get update && sudo apt-get upgrade ; } |& tee output.txt

In case you want to append the output to an existing logfile, add the -a option after tee.


To explain what it does:

  • { ... ; } groups the ... commands inside, so that the output redirections we will perform apply to all commands and not just the last one. Please pay attention on the space after { and before } as well as on the semicolon ; after all commands! (thanks @kos for telling me to avoid spawning a subshell)
  • sudo apt-get update && sudo apt-get upgrade are the example commands we want to run and record here. You may exchange this whole part with whatever you like.
  • |& (the "pipe") redirects both output streams (STDERR/standard error and STDOUT/standard output) of the command left of it to the STDIN (standard input) of the command on the right. (thanks @muru for teaching me about the & to redirect both STDOUT and STDERR)
  • tee output.txt copies everything it reads from STDIN to STDOUT and also saves it to output.txt. If the target file already exists, it will get overwritten silently. You can append to the file instead if you use tee -a output.txt.
share|improve this answer
    
About the script, i usually do this on the terminal. I use the script just for a little bit of fun and to learn some stuff. But thanks for the note on the redirections STERR and STDOUT to the same file, didn´t know i could do that. – macacomen98 Feb 14 at 20:01
    
If you like the answer, don't hesitate to accept it by clicking the grey tick symbol on the left of it :-) – Byte Commander Feb 14 at 20:03
    
I wish i could tick more than one answer, sorry. It is very usefull, but the other one helped me the most. But thanks anyway! – macacomen98 Feb 14 at 20:19
2  
Bash has |& for 2>&1 |. – muru Feb 14 at 23:21
1  
@macacomen98 ./file.txt or bash file.txt – muru Feb 15 at 18:14

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.