1

I am new on scripting on Linux. On my local Mysql database which runs on a Linux machine:

mysql> SELECT * FROM folder;
+-------+---------+
| user  | folder  |
+-------+---------+
| user1 | folder1 |
| user2 | folder2 |
| user3 | folder3 |
+-------+---------+

I need to read form the database "folder1" and send command on remote Linux " mkdir folder1"
so script can create automatic folder1-3. Remote Linux password is not an issue.

Now i am doing it manually

ssh root@www1.cyberciti.biz mkdir folder1
ssh root@www1.cyberciti.biz mkdir folder2
ssh root@www1.cyberciti.biz mkdir folder3
cnicutar
  • 178,505
  • 25
  • 365
  • 392

4 Answers4

1

sort answer like this

 #!/bin/bash
myvar=$(mysql -D database -u username -p  password -se "SELECT folder FROM folder"| xargs echo -n)
ssh root@www1.cyberciti.biz mkdir "$myvar"
Jayesh Bhoi
  • 24,694
  • 15
  • 58
  • 73
  • This does not work, because it also prints out the column name. – Andreas Florath Mar 18 '14 at 11:37
  • Always quote variables. What if "folder" contains `;rm -rf /`? – ghoti Mar 18 '14 at 11:37
  • @AndreasFlorath If you tested then what you think about this one http://stackoverflow.com/questions/17774405/bash-sql-query-outputs-to-variable – Jayesh Bhoi Mar 18 '14 at 11:41
  • @ghoti Thanks for your valuable suggestion. – Jayesh Bhoi Mar 18 '14 at 11:43
  • @Jayesh: Of course I tested it. And it prints out the column name:folder\n folder1\n folder2\n folder3\n – Andreas Florath Mar 18 '14 at 11:49
  • @AndreasFlorath How you test it? fire command `myvar=$(mysql -D database -u username -p password -se "SELECT folder FROM folder")` then `echo $myvar` see what output? – Jayesh Bhoi Mar 18 '14 at 12:28
  • @AndreasFlorath Perfectly working for me:) Like you tested partially like you fire direct command on terminal `mysql -D database -u username -p password -se "SELECT folder FROM folder"` and it print column name but i redirect data to array. – Jayesh Bhoi Mar 18 '14 at 12:42
  • Yes - you are right with the column name. Looks that starting mysql in the way you did changes the result - which I did not know. But still: when executing the whole script, it gives: 'ssh root@www1.cyberciti.biz mkdir folder1\n folder2\n folder3\n' what is not as expected. – Andreas Florath Mar 18 '14 at 18:08
1

You can do it in one line; here the test version. It's just prints out the commands. Drop the 'echo' to really execute the commands.

mysql testdb --batch --skip-column-names -p -e "select distinct(folder) from folder" | xargs -n 1 -I '{}' echo ssh root@www1.cyberciti.biz mkdir \"{}\"

Output:

ssh root@www1.cyberciti.biz mkdir "folder1"
ssh root@www1.cyberciti.biz mkdir "folder2"
ssh root@www1.cyberciti.biz mkdir "folder3"
Andreas Florath
  • 4,418
  • 22
  • 32
  • 1
    While this answer is technically correct, it's a bit limited in that an xargs solution can't be used to mark completed records, something that would be trivial in a bash while loop simply by adding an extra line. In general, we all get more out of StackOverflow if we provide the answers people *need*, even if they don't always ask exactly the right questions. – ghoti Mar 18 '14 at 11:42
  • This solution exactly does what the question ask for. Not more - not less. I feel not in the position to interpret what people maybe want to do in future. If there are new requirements or aspects: change it! (Maybe you should have a look in the one or other requirements management book: always give the people what they ask for. If you give them something they want and they don't ask for, they will not be happy.) – Andreas Florath Mar 18 '14 at 11:47
  • If your goal is to teach a lesson in communication, then this approach may work. On the other hand, if you work a little harder to understand the problem, the end result may be that the OP actually gets *help* rather than just another question. While your favourite requirements management book may work in other environments, here in StackOverflow, many of us actually want to help. A novel concept, I know, but it seems to be working. Imparting wisdom is better than merely imparting knowledge. – ghoti Mar 18 '14 at 15:21
  • Re-reading your comments after you posted a 'solution' with does not work adds some more evidence, that also here the KISS type of solution might be the one which gives everybody the most. Maybe my reaction is somewhat not obvious - but in my daily work I had to read source code as you wrote it, try to understand the core ideas and throw away all the things never used / needed (which also mostly eliminates most bugs). IMHO the way you wrote your 'solution' is exactly how it should *not* be done - and shows exactly: the longer the source the more bugs it contains. – Andreas Florath Mar 18 '14 at 19:19
  • That's an excellent point, and believe me, I see the benefit of KISS. I think we'll have to disagree on the strategy though. When I ask questions, I appreciate answers that consider needs that I haven't even realized I had. But your one-liner works, even better with some of your updates, so it gets a +1 from me too. Isn't it nice that we can recognize the benefits of each others' answers? :) – ghoti Mar 19 '14 at 11:44
0
while read id; do 
    ssh root@www1.cyberciti.biz "mkdir $id"
done < <(mysql -u $USER -p $PASSWORD $DATABASE -e "SELECT folder FROM folder;" --skip-column-names)
Josh Jolly
  • 11,258
  • 2
  • 39
  • 55
  • This does not work and prints out the usage of mysql. – Andreas Florath Mar 18 '14 at 11:35
  • Works fine for me (mysql: 5.1.65-enterprise, RHEL 5.6) - what is it having trouble with? – Josh Jolly Mar 18 '14 at 11:39
  • @Jayesh: Of course I tested it. For me this solution prints the usage. My installation: mysql Ver 14.14 Distrib 5.5.33, for debian-linux-gnu (x86_64) using readline 6.2. Just checked it again. Here is the problem: From man page: you cannot have a space between the option and the password. – Andreas Florath Mar 18 '14 at 11:54
0

There are good points in various answers here. Let's mix a cocktail.

First off, as mentioned in comments, you probably want to do this in a loop rather than a single command line. While xargs is a powerful, useful command, in this case it's likely that you'll want to space things out in order to insert additional functionality in the future.

Second, as has been discussed, you need to account for column heads. Andreas quite rightly criticized other answers for leaving out the --skip-column-names option.

Third, as it stands, your script will try to recreate directories if it's run a second time. You want to mark things as done, once directories are made.

So...

#!/bin/bash

sql="SELECT folder FROM folder WHERE created=NULL"

mysql_opts=()
mysql_opts+=(--skip-column-names)      # obvious
mysql_opts+=(--host=dbhost)            # database server
mysql_opts+=(--user=username)          # mysql username
mysql_opts+=(--password=password)      # mysql password
mysql_opts+=(-D dbname)                # database name

while read name; do
  if [[ ! $name =~ ^[[:alnum:]_]+$ ]]; then
    echo "ERROR: invalid characters in '$name'" >&2
  elif ssh remotehost "mkdir '/path/to/${name}'"; then
    mysql "${mysql_opts[@]}" -e"UPDATE folder SET created=NOW() WHERE folder='$name'"
  else
    echo "ERROR: failed to create '$name'" >&2
  fi
done < <( mysql "${mysql_opts[@]}" -e"$sql" )

When programming, always consider how much effort it will be to maintain things in the future. If options are clear and well documented, then when things break, you can fix them faster.

So, we're setting mysql's options in a bash array.

Then we're running through a loop. Input to the loop is the command after done on the last line. This is called "Process Substitution".

Within the loop, we have an if that first does some input validation (which could also be done in your SELECT), and if the folder name passes, runs your ssh command. But the ssh command is run as part of another if. If it is successful, we mark the record as complete, with a timestamp. If it isn't successful, we get noisy about it. (Obviously, you'll need a created column in the folder table.)

Obviously, you can do whatever you like with your errors -- send a pager message, and email, notify your monitoring system, etc. The important thing is that you're accounting for failure, and doing something about it. (What happens if there was a temporary network failure when you were running the last mkdir?)

Let me know if any of this is confusing. I'll be happy to clarify.

ghoti
  • 45,319
  • 8
  • 65
  • 104
  • One point which I do not understand is, why 'mysql ... select folder ...' behaves different from 'echo $(mysql ... select folder ...)'. Maybe it checks if it is connected to a terminal / tty and behaves different. (man page does not say anything about this.) Therefore the '--skip-column-names' is not always really needed - nevertheless it is always a good comment what you want to accomplish. – Andreas Florath Mar 18 '14 at 18:21
  • Sorry - but it looks that you never run your solution: there is a syntax error (replace last 'do' by 'fi') and looks that you miss the basics of SQL (NULL is never = NULL): http://dev.mysql.com/doc/refman/5.0/en/working-with-null.html. For me it is strange that you post code here which obviously was never tested. – Andreas Florath Mar 18 '14 at 18:37
  • Ah, good catch, thanks. I ran a version of it with mysql_opts and the loop, but just typed the `if` tree instead of pasting. Fixed! – ghoti Mar 18 '14 at 19:54
  • @AndreasFlorath - Regarding `--skip-column-names`, yes, it appears that with the `-s` option, mysql detects if it's running on a terminal and drops the column heads. You can run a `mysql ... -s -e"SELECT ..."`, then run the same command piped through `cat` to see the difference. If you specify `-s` twice, you drop the column head even without the pipe. After a short search, I can't find specific documentation on this behaviour either. – ghoti Mar 18 '14 at 19:59
  • I'll gladly upvote this even though it *might* be overkill in this particular scenario as I am all for anticipating problems and interpreting a question based on what someone is trying to achieve as opposed what is being asked literally. XY problems can be a pain in the ass and more people on SO should think like you do. – Adrian Frühwirth Mar 19 '14 at 09:34