simX
Unofficial Mac Genius
So a couple of UNIX related things that people were requesting I post about:
First off, the commands "tr", "cut", and "awk". Of course, it's really easy to learn about them via the "man" command, but I'll explain them here. GadgetLover also wanted me to post something about groups and permissions, so skip down to after the command explanations if you want to learn about those.
The tr command translates characters. There are 3 options: -c, -s, and -d. A regular tr command like the following:
tr ab cd
... will translate all occurences of "a" in the input to "c", and all occurences of "b" to "d". If you input this command all by itself, it will wait for you to type something in the terminal and press return before it spits out output. However, you can have the tr command process a file by using redirection characters, like this:tr -d aoeu < input.txt This instance will use input.txt as the input, and will instantly spit out the output after you press return, without waiting for further input. Also in the above example, the -d option deletes the characters. So any instance of "a" or "o" or "e" or "u" in input.txt will be deleted and the rest will be the output. The -s option will cause any character that is doubled in the output will drop one of the duplicate characters. For example, if the output (before showing it to you in the terminal window) were "aabbcc", and the -s option was used, the output would actually read "abc". Note that this occurs AFTER the translation, meaning you will never see duplicate characters in the output (by duplicate or doubled characters I mean a character that is immediately followed by the exact same character, as in "aa" or "bb"). The -c option seems to be flawed, however, because when you do it without specifying a file, it doesn't insert a correct line break to allow for new input -- it places your cursor directly after the output, making the output inevitably part of your next input. Try something like: tr -c a z in the terminal, and then give it some input and you'll see what I mean.
Now for the "cut" command. In my previous example, I used the command
cut -d" " -f2. The first option I will explain, -d, specifies the delimeter character. For example, if you have a text file with contents
378192 37192 94919. 38391 48393.t6504, and you use -d" ", there will be 5 fields in the above text file. If, however, you use -d".", there will only be 3 fields, and if you use -d"t", there will be 2 fields. See? Note that if you have 2 spaces in a text file next to one another, and you have the space set as the delimeter, one of them will have to be a field, because you cannot have an empty field. Now with my script, the -f option cuts fields. So when I specify -f2, I want field 2 in every line. That's how the script that found the process IDs of SETI@home works, since the pids are the second field when you initiate the "top" command (note that there are 2 spaces at the beginning of the lines that show process IDs and memory usage in top, which means the first space is a field, making the process ID the second field -- I struggled with this for a while until I noticed this). You can also have it cut certain character positions, by using the -c command, so if you use -c5, you will get the fifth character of each line. I should say that cut doesn't remove what you specify, it removes everything BUT what you specify.
OK, awk. It's very similar to "cut", except it is much more powerful, and it has a different syntax. The command awk '{print $1}' will result in all of the first fields in each line to be printed to the output. Note that this is different from cut, in the fact that when using fields, the delimitation is always a space (as far as I can tell), and even if you have two spaces next to each other, neither are considered fields, which is why in cut you have to use field 2 and in print you only use field 1 to get the process IDs from top. It should be noted that the stuff inside the '{ and }' is a program, so anything returned by the program inside there (with the correct syntax) will be outputted. This is a VERY brief explanation of a very powerful tool, so I highly suggest you look into it more by issuing the man awk command to learn more about it. There are even some examples near the end.
So now you should be able to understand basically how this script works:
top -l1 | grep SETI@home | tr -s " " | cut -d" " -f2 | tr "\n" " " > output.txt
sudo renice -20 `cat output.txt`
rm output.txt
First, I get one snapshot of memory usage. Then, I pipe (the | symbol is the pipe symbol, which means the output of the command before the symbol is used as the input for the command after the symbol) that to grep, which removes all lines which do not have the string "SETI@home" in it (note you can use the -i option for grep to make it case insensitive). That output is then piped to the tr command, which removes every duplicate instance of the space in the lines selected by grep (remember that the cut command, when shown two delimeters right next to each other, treats one as a field, so this can pose problems). Then I pipe THAT output to the cut command, which gets field 2 (the process IDs for my SETI@home instances). Then I pipe it to another translate character command which translates all line breaks ( \n is treated as a line break in tr) to spaces. Then this is outputted to the file output.txt. Then, I get temporary root access via te sudo command, and then I change the priority to -20 (highest priority). Note the two ` symbols around the command cat output.txt. Since the renice command does not accept input from a file, we have it replace the command cat output.txt with it's output, so the renice command thinks it is actually getting the process IDs (which it is, but we are fooling it because it is actually accepting input now). Then, I delete the output.txt file. Note that blb's shell script: sudo renice -20 `top -l1 | grep SETI@home | awk '{print $1}'` is much more elegant. First, it uses the awk command instead of all the cut and tr commands. It also uses only one line and eliminates the need for the intermediary output.txt file, because it replaces the whole last part of the command (inside the two ` symbols) with its output, so the renice command can do its job immediately.
Now for permissions. If you get a long listing of a directory in the terminal, as in the command ls -l, you'll see most lines of the listing for each file and directory look something like:
drwxr-xr-x 4 simmy staff 264 Dec 18 01:33 Public. These are the permissions. The first letter, in this case, a d, tells you what kind of file there is. If the first character is a d, that line is telling you about a directory. If there is a dash, it is telling you about a file. There are other letters that can appear here, but they are very rare. The next 3 characters are the permissions for the owner (the first name that appears -- in this case, "simmy"). r means there are read permissions, w means write permissions, and x means execute permissions. It is always in this order. If one of the 3 kinds of permissions is denied, you will see a dash in place of the letter. So in this case, the permissions for the owner, simmy, on this directory is to allow him to read, write, and execute (it doesn't really make sense for a directory, but it does for a file). The next 3 characters are for the group (the second name that appears -- in this case, "staff"). You read the permissions in the same way. In this case, the group "staff" has permission to read and execute, but not to write. The last 3 characters are permissions for anyone except the owner and people who are in the listed group. In this case, everyone else is allowed to read and execute as well. NOTE: Read and execute are, in fact, different in the UNIX operating system. Suppose you want somebody to be able to execute a shell script you made but not see how you performed it (for example, if you're a UNIX class teacher and you want to demonstrate that a certain exercise is possible, but you don't want the students to snoop around in the code). You might also want to allow someone to read the script, but not execute it (for example, if you were showing a malicious shell script that would delete some files on your hard drive -- people who only have read permissions but no execute permissions can look at the script, but they can't execute it). This is a big difference from the Classic MacOS permissions, which were simply read and write (read included execute).
(More in the next post, because I am reaching the maximum limit for characters in one post.)
First off, the commands "tr", "cut", and "awk". Of course, it's really easy to learn about them via the "man" command, but I'll explain them here. GadgetLover also wanted me to post something about groups and permissions, so skip down to after the command explanations if you want to learn about those.
The tr command translates characters. There are 3 options: -c, -s, and -d. A regular tr command like the following:
tr ab cd
... will translate all occurences of "a" in the input to "c", and all occurences of "b" to "d". If you input this command all by itself, it will wait for you to type something in the terminal and press return before it spits out output. However, you can have the tr command process a file by using redirection characters, like this:tr -d aoeu < input.txt This instance will use input.txt as the input, and will instantly spit out the output after you press return, without waiting for further input. Also in the above example, the -d option deletes the characters. So any instance of "a" or "o" or "e" or "u" in input.txt will be deleted and the rest will be the output. The -s option will cause any character that is doubled in the output will drop one of the duplicate characters. For example, if the output (before showing it to you in the terminal window) were "aabbcc", and the -s option was used, the output would actually read "abc". Note that this occurs AFTER the translation, meaning you will never see duplicate characters in the output (by duplicate or doubled characters I mean a character that is immediately followed by the exact same character, as in "aa" or "bb"). The -c option seems to be flawed, however, because when you do it without specifying a file, it doesn't insert a correct line break to allow for new input -- it places your cursor directly after the output, making the output inevitably part of your next input. Try something like: tr -c a z in the terminal, and then give it some input and you'll see what I mean.
Now for the "cut" command. In my previous example, I used the command
cut -d" " -f2. The first option I will explain, -d, specifies the delimeter character. For example, if you have a text file with contents
378192 37192 94919. 38391 48393.t6504, and you use -d" ", there will be 5 fields in the above text file. If, however, you use -d".", there will only be 3 fields, and if you use -d"t", there will be 2 fields. See? Note that if you have 2 spaces in a text file next to one another, and you have the space set as the delimeter, one of them will have to be a field, because you cannot have an empty field. Now with my script, the -f option cuts fields. So when I specify -f2, I want field 2 in every line. That's how the script that found the process IDs of SETI@home works, since the pids are the second field when you initiate the "top" command (note that there are 2 spaces at the beginning of the lines that show process IDs and memory usage in top, which means the first space is a field, making the process ID the second field -- I struggled with this for a while until I noticed this). You can also have it cut certain character positions, by using the -c command, so if you use -c5, you will get the fifth character of each line. I should say that cut doesn't remove what you specify, it removes everything BUT what you specify.
OK, awk. It's very similar to "cut", except it is much more powerful, and it has a different syntax. The command awk '{print $1}' will result in all of the first fields in each line to be printed to the output. Note that this is different from cut, in the fact that when using fields, the delimitation is always a space (as far as I can tell), and even if you have two spaces next to each other, neither are considered fields, which is why in cut you have to use field 2 and in print you only use field 1 to get the process IDs from top. It should be noted that the stuff inside the '{ and }' is a program, so anything returned by the program inside there (with the correct syntax) will be outputted. This is a VERY brief explanation of a very powerful tool, so I highly suggest you look into it more by issuing the man awk command to learn more about it. There are even some examples near the end.
So now you should be able to understand basically how this script works:
top -l1 | grep SETI@home | tr -s " " | cut -d" " -f2 | tr "\n" " " > output.txt
sudo renice -20 `cat output.txt`
rm output.txt
First, I get one snapshot of memory usage. Then, I pipe (the | symbol is the pipe symbol, which means the output of the command before the symbol is used as the input for the command after the symbol) that to grep, which removes all lines which do not have the string "SETI@home" in it (note you can use the -i option for grep to make it case insensitive). That output is then piped to the tr command, which removes every duplicate instance of the space in the lines selected by grep (remember that the cut command, when shown two delimeters right next to each other, treats one as a field, so this can pose problems). Then I pipe THAT output to the cut command, which gets field 2 (the process IDs for my SETI@home instances). Then I pipe it to another translate character command which translates all line breaks ( \n is treated as a line break in tr) to spaces. Then this is outputted to the file output.txt. Then, I get temporary root access via te sudo command, and then I change the priority to -20 (highest priority). Note the two ` symbols around the command cat output.txt. Since the renice command does not accept input from a file, we have it replace the command cat output.txt with it's output, so the renice command thinks it is actually getting the process IDs (which it is, but we are fooling it because it is actually accepting input now). Then, I delete the output.txt file. Note that blb's shell script: sudo renice -20 `top -l1 | grep SETI@home | awk '{print $1}'` is much more elegant. First, it uses the awk command instead of all the cut and tr commands. It also uses only one line and eliminates the need for the intermediary output.txt file, because it replaces the whole last part of the command (inside the two ` symbols) with its output, so the renice command can do its job immediately.
Now for permissions. If you get a long listing of a directory in the terminal, as in the command ls -l, you'll see most lines of the listing for each file and directory look something like:
drwxr-xr-x 4 simmy staff 264 Dec 18 01:33 Public. These are the permissions. The first letter, in this case, a d, tells you what kind of file there is. If the first character is a d, that line is telling you about a directory. If there is a dash, it is telling you about a file. There are other letters that can appear here, but they are very rare. The next 3 characters are the permissions for the owner (the first name that appears -- in this case, "simmy"). r means there are read permissions, w means write permissions, and x means execute permissions. It is always in this order. If one of the 3 kinds of permissions is denied, you will see a dash in place of the letter. So in this case, the permissions for the owner, simmy, on this directory is to allow him to read, write, and execute (it doesn't really make sense for a directory, but it does for a file). The next 3 characters are for the group (the second name that appears -- in this case, "staff"). You read the permissions in the same way. In this case, the group "staff" has permission to read and execute, but not to write. The last 3 characters are permissions for anyone except the owner and people who are in the listed group. In this case, everyone else is allowed to read and execute as well. NOTE: Read and execute are, in fact, different in the UNIX operating system. Suppose you want somebody to be able to execute a shell script you made but not see how you performed it (for example, if you're a UNIX class teacher and you want to demonstrate that a certain exercise is possible, but you don't want the students to snoop around in the code). You might also want to allow someone to read the script, but not execute it (for example, if you were showing a malicious shell script that would delete some files on your hard drive -- people who only have read permissions but no execute permissions can look at the script, but they can't execute it). This is a big difference from the Classic MacOS permissions, which were simply read and write (read included execute).
(More in the next post, because I am reaching the maximum limit for characters in one post.)