bash, cat - pipe - splitt - mysql är det möjligt utan variabler i bash?

Permalänk

bash, cat - pipe - splitt - mysql är det möjligt utan variabler i bash?

Hej sitter och funderar lite och håller på med ett script som är tänkt att spara information som kan vara intressant i en mysql db.. samt köra lite test på att ha mysql databasen på zfsonlinux dataset.. två flugor i en smäll typ..

iaf själva scriptet blir bash då det är linux som är oset och min första anhalt i att lära mig bash blir att plocka ut infon ifrån /proc/loadavg

min tanken är att få ganska många inlägg fort i databasen men endå ha någon form av nytta av datan..

iaf min tanke är att det borde gå att köra

cat /proc/loadavg | splitt *här dela textsträngen i 5 bitar* | mysql *här på något sätt använda dom fem bitarna i sql queryn..

eller måste jag använda variabler och dela upp informationen innan jag insertar den i databasen?

är rätt färsk på shell script men tänkte att de börjar väl bli dags att lära sig.. hittar dock inte mycket matnyttigt som är användbart här..

Permalänk
Medlem

cat /proc/loadavg | tr ' ' '\n' | while read line; do mysql --version; done

borde du kunna utgå ifrån, dock ändrar du så klart mysql --version till typ "mysql insert into database" (inte helt säker på mysql ifrån command linen)

Visa signatur

13600KF, RTX 4070 FE, B760I, 32GB DDR4, NR200P

Permalänk
Medlem

Något sånt här borde kunna generera din SQL:

awk '{ print "INSERT INTO foo ('a','b','c') VALUES (",$1,",",$2,",",$3,")" }' /proc/loadavg

Resultat:

INSERT INTO foo (a,b,c) VALUES ( 2.84 , 2.60 , 2.47 )

Det betyder att du kan göra liknande detta (du kan köra subkommandon genom $(cmd), alt `cmd`, i bash):

#!/bin/bash mysql -u youruser -p -e "$(awk '{ print "INSERT INTO foo ('a','b','c') VALUES (",$1,",",$2,",",$3,")" }' /proc/loadavg)" yourdb

Visa signatur

..:: RiJo ::..
Computer: Lenovo X300
Platform: Gentoo

Permalänk

för att testa lite gjorde ja ett script iaf.. såg nu att ni hade svarat..

#!/bin/bash set -- $(cat /proc/loadavg) echo $1 echo $2 echo $3 echo $4 echo $5 mysql --user=user --password=lösen --execute 'INSERT INTO stats.loadavg VALUES(NOW(), NOW(), "$1", "$2", "$3", 6, 413);' exit 0

när ja kör scriptet så echo ger rätt värden, och hårdkodar jag exakt som echo ger outputen så hamnar det i databasen men använder jag variabeln så får jag bara default värdet som om den inte får något värde..

har jag missat något med bash och variabler? spelar ingen roll om ja använder dubbelquotes, eller inga quotes..

Permalänk
Medlem

Jag skulle gissa att de single quotes som du använder runt din fråga gör att bash-variablerna inte avkodas.

Skickades från m.sweclockers.com

Visa signatur

..:: RiJo ::..
Computer: Lenovo X300
Platform: Gentoo

Permalänk
Skrivet av RiJo:

Jag skulle gissa att de single quotes som du använder runt din fråga gör att bash-variablerna inte avkodas.

Skickades från m.sweclockers.com

mysql --user=user --password=lösen --execute "INSERT INTO stats.loadavg VALUES(NOW(), NOW(), "$1", "$2", "$3", 6, 413);"

så funkade det som de ska, hade för mig de brukar funka att köra dubbla innanför single quotes.. men de där funkar ju bevisligen oxå..

Permalänk
Hedersmedlem
Skrivet av lambdan:

cat /proc/loadavg | tr ' ' '\n' | while read line; do mysql --version; done

borde du kunna utgå ifrån, dock ändrar du så klart mysql --version till typ "mysql insert into database" (inte helt säker på mysql ifrån command linen)

Det behöver bli giltig SQL-syntax av det hela, så input behöver "masseras" mer än bara med `tr`.

En notis är att `cat` direkt in i en pipe mer eller mindre alltid (finns några få rätt exotiska undantag) är en onödigt bökig konstruktion: skriv hellre

tr ' ' '\n' < /proc/loadavg | while

vilket utnyttjar direkt skalomdirigering. Jag skrev mer om skalomdirigering en annan gång på forumet; stycke 2 och nedåt, på ett ungefär.

Skrivet av RiJo:

Något sånt här borde kunna generera din SQL:

awk '{ print "INSERT INTO foo ('a','b','c') VALUES (",$1,",",$2,",",$3,")" }' /proc/loadavg

Resultat:

INSERT INTO foo (a,b,c) VALUES ( 2.84 , 2.60 , 2.47 )

Det betyder att du kan göra liknande detta (du kan köra subkommandon genom $(cmd), alt `cmd`, i bash):

#!/bin/bash mysql -u youruser -p -e "$(awk '{ print "INSERT INTO foo ('a','b','c') VALUES (",$1,",",$2,",",$3,")" }' /proc/loadavg)" yourdb

AWK låter som en typiskt bra lösning när det gäller att transformera textströmmar, när man väl vant sig vid syntaxen.

Skriv gärna `#!/bin/sh` (pekar enligt standard på ett POSIX-kompatibelt skal) i stället för `#!/bin/bash` när ett skript inte använder Bashspecifika konstruktioner. På vissa system är `/bin/sh` bara en symlänk till `/bin/bash`, varpå det aldrig kommer märkas någon kompatibilitetsskillnad i praktiken då Bash sväljer POSIX utan egentliga problem. På system där detta inte är fallet så är det dock onödigt bagage att dra igång Bash när det räcker med ett minimalt POSIX-skal; mer i ämnet finns att läsa på exempelvis Dash as /bin/sh → Why was this change made? [Ubuntu wiki].

Det är ett visserligen ett större problem om man slentrianmässigt anger `#!/bin/sh` när man egentligen vill att skriptet ska köras med just Bash för att man använder Bash-specifika funktioner (behändig referenslista ifall man är osäker, men det går också snabbt att testa direkt). Sådana skript kommer fungera på vissa system, men troligen krascha abrupt på andra — så kontentan är väl att alltid göra rätt, helt enkelt .

Visa signatur

Nu med kortare användarnamn, men fortfarande bedövande långa inlägg.

Permalänk
Hedersmedlem
Skrivet av EvilCrackMonkey:

mysql --user=user --password=lösen --execute "INSERT INTO stats.loadavg VALUES(NOW(), NOW(), "$1", "$2", "$3", 6, 413);"

så funkade det som de ska, hade för mig de brukar funka att köra dubbla innanför single quotes.. men de där funkar ju bevisligen oxå..

Dubbla innanför enkla tolkas inte; just enkla citattecken "dödar" det mesta av tolkning.

Din nuvarande lösning kommer åka på problem ifall någon av variablerna innehåller mellanslag. Bättre vore att använda enkla citattecken innanför dina dubbla, vilket inte "dödar" tolkningen, typ:

mysql --user=user --password=lösen --execute "INSERT INTO stats.loadavg VALUES(NOW(), NOW(), '$1', '$2', '$3', 6, 413);"

Notera dock att sådan här "naiv" sammanslagning av strängar kommer med en del finter; om indata här innehåller egna enkla citationstecken här så ligger man risigt till igen. Det är en av anledningarna till att man gärna använder ett mer uttrycksfullt API för databaskommunikation.

Hur löser man detta "ordentligt" i shell script så att det kan hantera snarast godtycklig indata? Man kan manuellt leta efter "dumma" tecken med exempelvis `tr` eller `sed`, eller kanske vara snillrik med `printf` (`%q` ger en "shell escaped" sträng via `printf`, som kanske snarare quotar för mycket) på något sätt, men ska man återuppfinna ordentlig indatakontroll så är det troligen mindre jobb (och bättre) att skriva om skriptet i Python/Perl/PHP/någonting som redan har vettiga bibliotek som sköter sådant.

Visa signatur

Nu med kortare användarnamn, men fortfarande bedövande långa inlägg.

Permalänk
Skrivet av phz:

Dubbla innanför enkla tolkas inte; just enkla citattecken "dödar" det mesta av tolkning.

Din nuvarande lösning kommer åka på problem ifall någon av variablerna innehåller mellanslag. Bättre vore att använda enkla citattecken innanför dina dubbla, vilket inte "dödar" tolkningen, typ:

mysql --user=user --password=lösen --execute "INSERT INTO stats.loadavg VALUES(NOW(), NOW(), '$1', '$2', '$3', 6, 413);"

Notera dock att sådan här "naiv" sammanslagning av strängar kommer med en del finter; om indata här innehåller egna enkla citationstecken här så ligger man risigt till igen. Det är en av anledningarna till att man gärna använder ett mer uttrycksfullt API för databaskommunikation.

Hur löser man detta "ordentligt" i shell script så att det kan hantera snarast godtycklig indata? Man kan manuellt leta efter "dumma" tecken med exempelvis `tr` eller `sed`, eller kanske vara snillrik med `printf` (`%q` ger en "shell escaped" sträng via `printf`, som kanske snarare quotar för mycket) på något sätt, men ska man återuppfinna ordentlig indatakontroll så är det troligen mindre jobb (och bättre) att skriva om skriptet i Python/Perl/PHP/någonting som redan har vettiga bibliotek som sköter sådant.

jag har sett att man kan använda php i cli form, men det kändes på något sätt inte rätt, men om det nu inte är helt opassande skulle det ju underlätta en hel del.. trodde faktiskt inte man körde php script som shellscript? antar att man kör #!/usr/bin/php om man ska använda php istället?

Permalänk

ja att få ihop det där med php var ingen större utmaning, men en klar fördel nu när jag vet att jag kan göra egna scripts i tex php antar att man kan använda vilket språk man vill, bara man lägger in sökvägen till tolken efter shebang..

tack för hjälpen alla inblandade även om det inte blev som det var tänkt från början