Linux за българи: Форуми

Програмиране => Общ форум => Темата е започната от: PaperNick в Aug 24, 2014, 21:35



Титла: Помощ за написването на едно скриптче
Публикувано от: PaperNick в Aug 24, 2014, 21:35
Здравейте,
Опитвам се да напиша скрипт, който да взима залеза от интернет и ако времето на залеза е равно на системното време, да се стартира програмата redshiftgui.

От един друг скрипт намерих как да взема залеза:
Код
GeSHi ():
  1. #!/bin/bash
  2.  
  3. WOEID="839722" #from weather.yaoo.com link for your city
  4.  
  5.  
  6. # get weather and dump into temp file
  7. if $(wget --no-cache -q "http://weather.yahooapis.com/forecastrss?w=$WOEID" -O /tmp/time);
  8. then
  9. mv /tmp/time /tmp/sunset.TMP
  10. fi
  11.  
  12. SUNSET=`cat /tmp/sunset.TMP | grep astronomy | sed -e 's/.*sunset="//g' | sed -e 's/".*//g'`
  13.  
  14. LOCALTIME= date +'%I:%M'
  15.  
И сега остава само да сравня SUNSET с LOCALTIME и ако са равни, да се стартира redshiftgui.
Ето тук не можах да се сетя как ще стане. Ако имате идеи, споделяйте.

Благодаря ;)


Титла: Re: Помощ за написването на едно скриптче
Публикувано от: Stancho_25 в Aug 24, 2014, 22:16
Може би малко глупав, но ето ти вариант с Гном терминал

Код
GeSHi (Bash):
  1. #!/bin/bash
  2.  
  3. WOEID="4363" #from weather.yaoo.com link for your city
  4.  
  5.  
  6. # get weather and dump into temp file
  7. if $(wget --no-cache -q "http://weather.yahooapis.com/forecastrss?w=$WOEID" -O /tmp/time);
  8. then
  9. mv /tmp/time /tmp/sunset.TMP
  10. fi
  11.  
  12. SUNSET=`cat /tmp/sunset.TMP | grep astronomy | sed -e 's/.*sunset="//g' | sed -e 's/ .*//g'`
  13.  
  14. LOCALTIME=`date +'%l:%M'`
  15.  
  16. if [ "$LOCALTIME" == "$SUNSET" ]
  17. then
  18. gnome-terminal
  19. fi


Има промяна на 12-ти ред в последния sed. Целта е да се вземе само часа без PM накрая. Също и 14-ти - формата на часа да е 1...12 вместо 01..12 за да мине сравняването.


Титла: Re: Помощ за написването на едно скриптче
Публикувано от: PaperNick в Aug 24, 2014, 22:54
Благодаря много, работи перфектно!


Out of curiosity, не може ли задача да се осъществи по по-елегантен начин? В момента скрипта трябва да се стартира през определен период от време за да прави проверката. Няма ли да е по-добре когато се стартира скрипта, да се отвори процес който да казва: "стартирай програмата в 8:14 (залеза)", като този час се взима от променливата SUNSET. Разтърсих се в интернет, но не намерих упътване как да пусна програма в определен час.


Титла: Re: Помощ за написването на едно скриптче
Публикувано от: go_fire в Aug 24, 2014, 22:56
Почти: man cron


Титла: Re: Помощ за написването на едно скриптче
Публикувано от: PaperNick в Aug 24, 2014, 23:03
Хе-хе, уникални сте хора. Явно няма нещо което да не знаете ;D

Мерси go_fire ;)


Титла: Re: Помощ за написването на едно скриптче
Публикувано от: d0ni в Aug 24, 2014, 23:44
може да спестиш малко от скрипта като заобиколиш временния файл с:

Цитат
SUNSET=`wget -q -S -O - 'http://weather.yahooapis.com/forecastrss?w=$WOEID' 2> /dev/null | grep astronomy | sed -e 's/.*sunset="//g' | sed -e 's/".*//g'`


Титла: Re: Помощ за написването на едно скриптче
Публикувано от: laskov в Aug 25, 2014, 13:38
... да се отвори процес който да казва: "стартирай програмата в 8:14 (залеза)", като този час се взима от променливата SUNSET. Разтърсих се в интернет, но не намерих упътване как да пусна програма в определен час.
Почти: man cron
cron не е подходящ. Той стартира повтарящи се в един и същ час (ден/дата) задачи. В случая, понеже часът се променя:

man at


Титла: Re: Помощ за написването на едно скриптче
Публикувано от: PaperNick в Aug 25, 2014, 16:19
Наистина с at е по-удачно да се подходи, но поради някакви причини, изобщо не се получава.

Пробвах един примерен ред в конзолата:
Цитат
echo "redshiftgui" | at 4:18 pm today

След това ми изписва:
Цитат
warning: commands will be executed using /bin/sh
job 39 at Mon Aug 25 16:18:00 2014
Всичко изглежда наред, но когато часа настъпи, нищо не се получава. Замених redshiftgui с thunar, но отново нищо.

Като временно решение, сложих един else в края на скрипта, който го презарежда отново през 1 минута.
Код
GeSHi (Bash):
  1. #!/bin/bash
  2. DIR_OF_FILE="$( cd "$( dirname "$0" )" && pwd )"
  3. WOEID="839722" #from weather.yaoo.com link for your city
  4.  
  5. # get weather and dump into temp file
  6. if $(wget --no-cache -q "http://weather.yahooapis.com/forecastrss?w=$WOEID" -O /tmp/time);
  7. then
  8. mv /tmp/time /tmp/sunset.TMP
  9. fi
  10.  
  11. SUNSET=`cat /tmp/sunset.TMP | grep astronomy | sed -e 's/.*sunset="//g' | sed -e 's/ .*//g'`
  12.  
  13. LOCALTIME=`date +'%l:%M'`
  14.  
  15. if [ "$LOCALTIME" == "$SUNSET" ]
  16. then
  17. redshiftgui
  18. else
  19. sleep 60; bash -c '$DIR_OF_FILE/SunsetScript.sh'
  20. fi


Титла: Re: Помощ за написването на едно скриптче
Публикувано от: jet в Aug 25, 2014, 18:10
ако пускаш програми през cron, трябва в скрипта всички програми които викаш да са с пълния път до тях.


Титла: Re: Помощ за написването на едно скриптче
Публикувано от: PaperNick в Aug 25, 2014, 18:22
Тази идея с else накрая на скрипта не е добра, защото Task Manager-a се пълни с процеси ;D

Та, преди малко зададох cron да пуска някаква програма всяка минута, но отново не се отваря...

Ето съдържанието на crontab:
Код:
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow   command
* * * * * /usr/bin/thunar # JOB_ID_1

Да не би да има някакви проблеми с правата и да не може да чете?


Титла: Re: Помощ за написването на едно скриптче
Публикувано от: neter в Aug 25, 2014, 18:27
LOCALTIME=`date +'%l:%M'`
При така оформения код това трябва да е
Цитат
LOCALTIME=`date +'%l:%M' | tr -d ' '`
тъй като командата date оставя интервал пред часове, по-малки от 10, и той ще навреди на приравняването със стойността на $SUNSET. Разбира се, при 12-часов формат залезът винаги ще е в час, по-малък от 10, така че, вместо промяна в $LOCALTIME, може просто да се добави интервал пред стойността на $SUNSET.

При положение, че залезът се случва веднъж в денонощието, е пълно разхищение скриптът да се изпълнява на всяка минута. Предложението за crontab на go_fire е добро, като единствено трябва да се добави малко динамичност, заради променящия се час на залеза. За целта може кода от LOCALTIME нататък да го замениш с
Код
GeSHi (Bash):
  1. let hour=`echo $SUNSET | cut -d: -f1`+12
  2. minute=`echo $SUNSET | cut -d: -f2`
  3.  
  4. /usr/bin/crontab -l | { cat; echo "$minute $hour * * * /пълен/път/до/sunset_redshiftgui.sh"; } | /usr/bin/crontab -
След което скриптът да се сложи за изпълнение в crontab на обяд (или друг удобен час, в който няма вероятност слънцето да залезе). Третият ред се грижи да сложи в crontab задача за изпълнението на скрипта sunset_redshiftgui.sh в нужните час и минута. Въпросният скрипт може да изглежда така
Код
GeSHi (Bash):
  1. #!/bin/bash
  2.  
  3. export DISPLAY=:0
  4. /пълен/път/до/redshiftgui &
  5.  
  6. /usr/bin/crontab -l | grep -v sunset_redshiftgui | /usr/bin/crontab -
С export-а се задава екран, на който да се стартира графичното приложение (доколкото разбрах redshiftgui е такова), като цифрата трябва да се промени, ако не е 0. Последният ред се грижи за премахването на станалата излишна задача в crontab (ще бъде добавена нова при следващото изпълнение на другия скрипт). Гледай името на този скрипт да е такова, че да си сигурен, че няма да се съдържа в името на друг скрипт в crontab, защото така ще бъдат изтрити и двете задачи.

И един въпрос. Уреждайки случки при залез не е ли редно да уредиш съответни случки и при изгрев?

редакция: Малка, но важна, корекция във вземането на часа от $SUNSET. И добавяне на пълни пътища за crontab.


Титла: Re: Помощ за написването на едно скриптче
Публикувано от: PaperNick в Aug 25, 2014, 19:02
Доста интересно. Има малки детайли които не се забелязват с просто око.

Можеш ли малко по-подробно да обясниш, защото се обърках, а и не вдявам много от bash?
Значи, като редактирам кода след LOCALTIME, слагам скрипта да се стартира през cron на обяд. После какво става с втория скрипт и как изтрива предишните задачи в cron? Нещо ми се губи картината...

Изгревът не ме засяга, защото около 8-9 часа е вече светло, но иначе е интересно да се направи и за него, просто за упражнение :)


Титла: Re: Помощ за написването на едно скриптче
Публикувано от: d0ni в Aug 25, 2014, 19:32
всъщност някой се е сетил отдавна за такова нещо - http://www.risacher.org/sunwait/ ($2)

задаваш му координатите, на които се намираш, и програмката чака докато изгрее / залезе слънцето и exit-ва

Цитат
The feature that makes this program slightly unique is that it can be set to wait specific event (such as 5 minutes before sunrise), then exit. This makes it useful for 'cron' jobs or 'scheduled tasks' when you want something to happen relative to sunrise, sunset, or some other astronomical event.



Титла: Re: Помощ за написването на едно скриптче
Публикувано от: neter в Aug 25, 2014, 19:35
Значи, като редактирам кода след LOCALTIME
Не "след", а "от" - редът, в който се задава променливата LOCALTIME също отпада.

Код
GeSHi (Bash):
  1. /usr/bin/crontab -l | { cat; echo "$minute $hour * * * /пълен/път/до/sunset_redshiftgui.sh"; } | /usr/bin/crontab -
Това е редът в първия скрипт, който ще добавя подобна задача в crontab
Цитат
13 20 * * * /пълен/път/до/sunset_redshiftgui.sh
която ще изпълнява втория скрипт в конкретните за деня час и минута на залеза (в примера се задава час 20:13). Ето редът от bash кода на части, за да го разбереш
Код
GeSHi (Bash):
  1. /usr/bin/crontab -l
Това изкарва пълен списък с текущо наличните задачи в crontab.
Код
GeSHi (Bash):
  1. { cat; echo "$minute $hour * * * /пълен/път/до/sunset_redshiftgui.sh"; }
Това взема подадения текст на списъка (командата cat) и добавя към него ред със задачата, която ще извиква втория скрипт.
Код
GeSHi (Bash):
  1. /usr/bin/crontab -
Това налива целия получен текст (досегашното съдържание на crontab плюс новата задача) в crontab.
Правата черта (pipe, "|") между частите служи за препращане на изхода от предходната към следващата част за обработка.

Когато часът настъпи и crontab изпълни втория скрипт, скриптът си прави неговите действия по включване на нужното приложение и накрая с този ред
Код
GeSHi (Bash):
  1. /usr/bin/crontab -l | grep -v sunset_redshiftgui | /usr/bin/crontab -
се премахва задачата, включила този скрипт - вече ще е излишна, тъй като на следващия ден задачата ще трябва да се изпълни с друг час и за добавянето ѝ ще се погрижи първият скрипт. Първата и третата част от този ред вече ти ги обясних по-горе, а втората част
Код
GeSHi (Bash):
  1. grep -v sunset_redshiftgui
указва да се вземе целият текст от списъка с cron задачи без редовете, съдържащи текста "sunset_redshiftgui" (името на втория скрипт). Така премахваме от списъка cron задачата с втория скрипт и наливаме изчистения списък в crontab.

Когато пак дойде обяд, първият скрипт ще добави cron задача за изпълнението на втория скрипт с конкретния за деня час на залеза, и когато дойде часът на залеза и вторият скрипт се изпълни, той ще се погрижи да премахне собствената си cron задача, и т.н.


Титла: Re: Помощ за написването на едно скриптче
Публикувано от: jet в Aug 25, 2014, 20:08
тези самомодифициращи се cron-ове са много трудми за дебъгване (ако нещо не работи), а и 6 месеца по-късно като трябва да правиш нещо, ще се чудиш какво си правил и защо си го правил

друг вариант е един cron job на обяд да разбере времето на залеза и да генерира единичен "at" с точното време и с това което трябва да се случи.


Титла: Re: Помощ за написването на едно скриптче
Публикувано от: PaperNick в Aug 25, 2014, 20:14
Благодаря за подробното обяснение neter, вече ми е много по-ясно.

Мисля, че вече имам достатъчно материал да човъркам. Благодаря на всички за идеите и подкрепата :)


Титла: Re: Помощ за написването на едно скриптче
Публикувано от: PaperNick в Aug 29, 2014, 22:28
Днес имах малко свободно време и реших да напиша скрипта. Идеята на Jet да използвам cron и at ми се стори най-лесна за реализиране, и затова се захванах с нея.

Ето го и самия скрипт:
Код
GeSHi (Bash):
  1. #!/bin/bash
  2.  
  3. WOEID="839722" # From weather.yahoo.com link for your city
  4.  
  5. # Get weather and dump into temp file
  6. if $(wget --no-cache -q "http://weather.yahooapis.com/forecastrss?w=$WOEID" -O /tmp/time);
  7. then
  8. mv /tmp/time /tmp/sunset.TMP
  9. fi
  10.  
  11. Sunrise=`cat /tmp/sunset.TMP | grep astronomy | sed -e 's/.*sunrise="//g' | sed -e 's/ .*//g'`
  12.  
  13. Sunset=`cat /tmp/sunset.TMP | grep astronomy | sed -e 's/.*sunset="//g' | sed -e 's/ .*//g'`
  14. let hourSunset=`echo $Sunset | cut -d: -f1`+12
  15. minuteSunset=`echo $Sunset | cut -d: -f2`
  16. sunset24=$hourSunset:$minuteSunset;
  17.  
  18. # Converts the Sunrise to Timestamp with the current date
  19. dateOnly=`date +'%Y-%m-%d '`; # Current date with space in the end
  20.  
  21. sunriseForStamp=$dateOnly$Sunrise:00;
  22. sunriseStamped=`date -d "$sunriseForStamp" "+%s"`
  23.  
  24. # Converts the Sunset to Timestamp with the current date
  25. sunsetForStamp=$dateOnly$sunset24:00;
  26. sunsetStamped=`date -d "$sunsetForStamp" "+%s"`
  27.  
  28. # Converts Local time to Timestamp
  29. localTime=`date +'%Y-%m-%d %H:%M:00'`;
  30. localTimeStamped=`date -d "$localTime" "+%s"`
  31.  
  32. # Sunrise
  33. if [ $localTimeStamped -le $sunriseStamped ]; then
  34. redshiftgui
  35. fi
  36.  
  37. # Sunset
  38. if [ $localTimeStamped -lt $sunsetStamped ]; then
  39. `echo "export DISPLAY=:0 && /usr/bin/redshiftgui" | at $sunset24 today`;
  40.  
  41. elif [ $localTimeStamped -ge $sunsetStamped ]; then
  42. redshiftgui
  43. fi

След това пуснах един cron job на скрипта ($2) и всичко се автоматизира.

Като цяло ми беше доста полезно, защото понаучах синтакса на Bash.
Благодаря отново на всички отзовали се, без вашата помощ нямаше да успея да го напиша. Рядко се срещат печени хора като вас [_]3