Deprecated: Creation of dynamic property wpdb::$categories is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/wp-db.php on line 668

Deprecated: Creation of dynamic property wpdb::$post2cat is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/wp-db.php on line 668

Deprecated: Creation of dynamic property wpdb::$link2cat is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/wp-db.php on line 668

Deprecated: Return type of WP_Theme::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-theme.php on line 554

Deprecated: Return type of WP_Theme::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-theme.php on line 595

Deprecated: Return type of WP_Theme::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-theme.php on line 535

Deprecated: Return type of WP_Theme::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-theme.php on line 544

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-includes/comment-template.php on line 1745

Deprecated: wp_getimagesize(): Implicitly marking parameter $image_info as nullable is deprecated, the explicit nullable type must be used instead in /home/inovacao/public_html/yeapf.com/wp/wp-includes/media.php on line 5072

Deprecated: Return type of WP_REST_Request::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/rest-api/class-wp-rest-request.php on line 960

Deprecated: Return type of WP_REST_Request::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/rest-api/class-wp-rest-request.php on line 980

Deprecated: Return type of WP_REST_Request::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/rest-api/class-wp-rest-request.php on line 992

Deprecated: Return type of WP_REST_Request::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/rest-api/class-wp-rest-request.php on line 1003

Deprecated: Return type of WP_Block_List::current() should either be compatible with Iterator::current(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-list.php on line 151

Deprecated: Return type of WP_Block_List::next() should either be compatible with Iterator::next(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-list.php on line 175

Deprecated: Return type of WP_Block_List::key() should either be compatible with Iterator::key(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-list.php on line 164

Deprecated: Return type of WP_Block_List::valid() should either be compatible with Iterator::valid(): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-list.php on line 186

Deprecated: Return type of WP_Block_List::rewind() should either be compatible with Iterator::rewind(): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-list.php on line 138

Deprecated: Return type of WP_Block_List::offsetExists($index) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-list.php on line 75

Deprecated: Return type of WP_Block_List::offsetGet($index) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-list.php on line 89

Deprecated: Return type of WP_Block_List::offsetSet($index, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-list.php on line 110

Deprecated: Return type of WP_Block_List::offsetUnset($index) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-list.php on line 127

Deprecated: Return type of WP_Block_List::count() should either be compatible with Countable::count(): int, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-list.php on line 199

Deprecated: Jetpack::setup_xmlrpc_handlers(): Implicitly marking parameter $xmlrpc_server as nullable is deprecated, the explicit nullable type must be used instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/class.jetpack.php on line 934

Deprecated: Automattic\Jetpack\Connection\Manager::setup_xmlrpc_handlers(): Implicitly marking parameter $xmlrpc_server as nullable is deprecated, the explicit nullable type must be used instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/vendor/automattic/jetpack-connection/src/class-manager.php on line 123

Deprecated: Creation of dynamic property Automattic\Jetpack\Connection\Manager::$error_handler is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/vendor/automattic/jetpack-connection/src/class-manager.php on line 93

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Instagram_Gallery::$is_wpcom is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-instagram-gallery.php on line 23

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Mailchimp::$wpcom_is_wpcom_only_endpoint is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-mailchimp.php on line 17

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Tweetstorm_Gather::$wpcom_is_wpcom_only_endpoint is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-tweetstorm-gather.php on line 21

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Tweetstorm_Gather::$is_wpcom is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-tweetstorm-gather.php on line 22

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Gutenberg_Available_Extensions::$wpcom_is_site_specific_endpoint is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/gutenberg-available-extensions.php on line 20

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Memberships::$wpcom_is_wpcom_only_endpoint is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php on line 23

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Memberships::$wpcom_is_site_specific_endpoint is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/memberships.php on line 24

Deprecated: Creation of dynamic property WPCOM_REST_API_V2_Endpoint_Subscribers::$wpcom_is_wpcom_only_endpoint is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/_inc/lib/core-api/wpcom-endpoints/subscribers.php on line 15

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/extensions/blocks/podcast-player/podcast-player.php on line 160

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/extensions/blocks/podcast-player/podcast-player.php on line 160

Deprecated: Creation of dynamic property POMO_FileReader::$is_overloaded is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/pomo/streams.php on line 26

Deprecated: Creation of dynamic property POMO_FileReader::$_pos is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/pomo/streams.php on line 29

Deprecated: Creation of dynamic property POMO_FileReader::$_f is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/pomo/streams.php on line 160

Deprecated: Creation of dynamic property MO::$_gettext_select_plural_form is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/pomo/translations.php on line 293

Deprecated: Creation of dynamic property Automattic\Jetpack\Sync\Queue::$random_int is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/vendor/automattic/jetpack-sync/src/class-queue.php on line 38

Deprecated: Creation of dynamic property Automattic\Jetpack\Sync\Queue::$random_int is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/vendor/automattic/jetpack-sync/src/class-queue.php on line 38

Deprecated: Creation of dynamic property Publicize_UI::$in_jetpack is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/publicize.php on line 53

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/widgets/migrate-to-core/image-widget.php on line 195

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/widgets/migrate-to-core/gallery-widget.php on line 56

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/calypsoify/class-jetpack-calypsoify.php on line 130

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/calypsoify/class-jetpack-calypsoify.php on line 131

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/calypsoify/class-jetpack-calypsoify.php on line 135

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/calypsoify/class-jetpack-calypsoify.php on line 136

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/calypsoify/class-jetpack-calypsoify.php on line 137

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 219

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 220

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 227

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 229

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 231

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 248

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 249

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 267

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 268

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 270

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 271

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 273

Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/simple-payments/simple-payments.php on line 275

Deprecated: Creation of dynamic property POMO_FileReader::$is_overloaded is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/pomo/streams.php on line 26

Deprecated: Creation of dynamic property POMO_FileReader::$_pos is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/pomo/streams.php on line 29

Deprecated: Creation of dynamic property POMO_FileReader::$_f is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/pomo/streams.php on line 160

Deprecated: Creation of dynamic property MO::$_gettext_select_plural_form is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/pomo/translations.php on line 293

Deprecated: Creation of dynamic property WPCOM_Widget_Goodreads::$shelves is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/widgets/goodreads.php on line 33

Deprecated: DateTime::__construct(): Passing null to parameter #1 ($datetime) of type string is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/script-loader.php on line 333

Deprecated: Creation of dynamic property WP_Block_Type::$skip_inner_blocks is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-type.php on line 347

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-type.php on line 347

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-type.php on line 347

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-type.php on line 347

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-type.php on line 347

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-type.php on line 347

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-type.php on line 347

Deprecated: Creation of dynamic property WP_Block_Type::$plan_check is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-type.php on line 347

Deprecated: Creation of dynamic property Jetpack_Shortcode_Unavailable::$shortcodes is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/shortcodes/unavailable.php on line 19

Deprecated: ltrim(): Passing null to parameter #1 ($string) of type string is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/wp-db.php on line 3030

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$object_id is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-term.php on line 198

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383

Warning: Cannot modify header information - headers already sent by (output started at /home/inovacao/public_html/yeapf.com/wp/wp-includes/class-wp-block-list.php:14) in /home/inovacao/public_html/yeapf.com/wp/wp-includes/feed-rss2.php on line 8
<br /> <b>Deprecated</b>: Creation of dynamic property WP_Term::$cat_ID is deprecated in <b>/home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php</b> on line <b>378</b><br /> <br /> <b>Deprecated</b>: Creation of dynamic property WP_Term::$category_count is deprecated in <b>/home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php</b> on line <b>379</b><br /> <br /> <b>Deprecated</b>: Creation of dynamic property WP_Term::$category_description is deprecated in <b>/home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php</b> on line <b>380</b><br /> <br /> <b>Deprecated</b>: Creation of dynamic property WP_Term::$cat_name is deprecated in <b>/home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php</b> on line <b>381</b><br /> <br /> <b>Deprecated</b>: Creation of dynamic property WP_Term::$category_nicename is deprecated in <b>/home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php</b> on line <b>382</b><br /> <br /> <b>Deprecated</b>: Creation of dynamic property WP_Term::$category_parent is deprecated in <b>/home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php</b> on line <b>383</b><br /> Desenvolvimento – Blog do Esteban http://www.yeapf.com/wp Espalhar informação no intuito de melhorar a vida de quem programa Sun, 13 Jun 2021 15:25:39 +0000 pt-BR hourly 1 https://wordpress.org/?v=5.8.12 85824673 Short Unique Identifier http://www.yeapf.com/wp/?p=626 Thu, 10 Jun 2021 19:00:01 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383
http://www.yeapf.com/wp/?p=626
Deprecated: ltrim(): Passing null to parameter #1 ($string) of type string is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/wp-db.php on line 3030

Deprecated: Creation of dynamic property Jetpack_Carousel::$localize_strings is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-content/plugins/jetpack/modules/carousel/jetpack-carousel.php on line 353

Recentemente se me apresentou o problema de migrar um banco de dados de identificadores auto-incrementais para identificadores universais únicos (UUID).

A vantagem do UUID é bem conhecida e acabam sobrepujando as desvantagens. A proposta deste artigo é fornecer uma solução palatável para balancear as vantagens (unicidade principalmente) com as desvantagens (comprimento principalmente)

O que segue é uma pequena implementação de proposta de solução.

<?php
function calcEntropy($str)
{
  // algoritmo de Shannon para cálculo da entropia
  $chars = array();

  $charcount = 0;
  $i         = strlen($str);
  while ($i > 0) {
    $i--;
    $thischar = substr($str, $i, 1);
    if (!isset($chars[ord($thischar)])) {
      $chars[ord($thischar)] = 0;
    }
    $chars[ord($thischar)]++;
    $charcount++;
  }

  $entropy = 0.0;
  foreach ($chars as $val) {
    $p       = $val / $charcount;
    $entropy = $entropy - ($p * log($p, 2));
  }

  return $entropy;
}

function genUuid()
{
  /* ver https://www.php.net/manual/en/function.uniqid.php#94959 */
  return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
    random_int(0, 0xffff), random_int(0, 0xffff),
    random_int(0, 0xffff),
    random_int(0, 0x0fff) | 0x4000,
    random_int(0, 0x3fff) | 0x8000,
    random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff)
  );
}

function dec2hex($number)
{
    $hv = array('0','1','2','3','4','5','6','7', '8','9','A','B','C','D','E','F');
    $ret = '';
    while($n != '0') {
        $ret = $hv[bcmod($n,'16')].$ret;
        $n = bcdiv($n,'16',0);
    }
    return $ret;
}

function genSUUID($prefix='', $maxLen=18) {
  $charset = "qwertyuiopasdfghjklzxcvbnm" .
             "QWERTYUIOPASDFGHJKLZXCVBNM" .
             "0123456789_";
  $max = strlen($charset);
  $prefix = str_pad($prefix,2,'0',STR_PAD_LEFT);

  $ts = dec2hex(date("y").str_pad(date("z"),3,'0', STR_PAD_LEFT).date("B"));
  $ret = $prefix.$ts;
  while(strlen($ret)<$maxLen) {
    $ret .= substr($charset,random_int(0,$max),1);
  }
  return $ret;
}

// exemplo e cálculo de entropia
$largo = 20;
echo "\nGerando SUUID\n";
echo "# - " . str_pad("SUUID", $largo) . " - Entropia\n";
$e = 0;
for ($i = 0; $i < 10; $i++) {
  $SUUID   = genSUUID("xyz", $largo);
  $entropy = calcEntropy($SUUID);
  $e += $entropy;
  echo "$i - " . $SUUID . " - " . calcEntropy($SUUID) . "\n";
}
echo "Entropia média = " . ($e / 10) . "\n";  

$largo = 12;
echo "\nGerando md5(SUUID)\n";
echo "# - " . str_pad("SUUID", 32) . " - Entropia\n";
$e = 0;
for ($i = 0; $i < 10; $i++) {
  $SUUID   = md5(genSUUID("xyz", $largo));
  $entropy = calcEntropy($SUUID);
  $e += $entropy;
  echo "$i - " . $SUUID . " - " . calcEntropy($SUUID) . "\n";
}
echo "Entropia média = " . ($e / 10) . "\n";

echo "\nGerando UUID canônico\n";
echo "# - " . str_pad("UUID", 36) . " - Entropia\n";
$e = 0;
for ($i = 0; $i < 10; $i++) {
  $uuid    = genUuid();
  $entropy = calcEntropy($uuid);
  $e += $entropy;
  echo "$i - " . $uuid . " - " . calcEntropy($uuid) . "\n";
}
echo "Entropia média = " . ($e / 10) . "\n";
 

A função hex2ec() apenas serve para transformar um decimal em hexadecimal. Deixarei de lado as explicações.

Me concentrarei em genSUUID().

$prefix é um prefixo que usaremos para identificar o servidor. No caso ele aceita até 2 caracteres. Se o conjunto for [ a-z A-Z 0-9 ] cada caractere representa 62 unidades. 62^2=3844 servidores.

$charset é o conjunto de caracteres que iremos usar para representar o identificador.

$ts é a representação do tempo. Ela toma o ano com dois dígitos (acho que nos podemos permitir voltar ao esquema de dois dígitos até o próximo milênio) seguido de um identificador de três dígitos representando o dia no ano (isso é mais econômico que mm/dd) e finalizado pela representação swatch de hora, minuto do timestamp corrente. (Um dia tem 86400 segundos, ao passo que os beats do swatch divide o dia em 1000 partes. Como a ideia aqui não é precisão mas sim unicidade mantendo uma aproximação de quando foi gerado o id, essa resolução é aceitável).

Finalmente o prefixo, a representação do tempo são colados e adicionamos um conjunto de caracteres aleatório do conjunto indicado no $charset.

O que obtemos é um identificador com alta probabilidade de ser único que ao mesmo tempo nos informa em qual servidor e data foi criado com uma resolução de 1 minuto e 26,4 segundos.

Ele é o suficientemente menor que o UUID como para atrair o interesse (lembre que quanto menor seja seu índice no banco, menos RAM vai consumir sua consulta entregando resultados mais velozes)

Ao mesmo tempo, ele tem informação auto-contida que pode orientar na hora de depurar quem deu origem à informação.

Caso for utilizar em produção, lembre que a coluna que irá conter essa informação deve ser Case Sensitive (que aliás, também impacta positivamente na performance) e não precisa ser UTF8 sendo suficiente ASCII.


Atualização Por pura curiosidade implementei o algoritmo de Shannon para calcular a entropia de um string. Depois adicionei dois testes comparativos: o md5() do SUUID e o UUID. Para minha surpresa o SUUID apresenta valores de entropia equivalentes ao UUID mas com menos caracteres.

 Generating SUUID (32 characters)
Number of items represented: 3,850,278.001.389.542.008.853.330.205.498.027,278,336
- SUUID - Entropy
0 - xyz142EB295J5Vt1EzAtc3N6QLIZz2TZ - 4.3903195311148
1 - xyz142EB29 or DgyH2twFrNX9wWlRIAWz - 4.5389097655574
2 - xyz142EB295qSYM3Px7r1OnaUYGHwpro - 4.6875
3 - xyz142EB29Bal8PBFFERITHJKaCBIFCp - 4.2889097655574
4 - xyz142EB29z14aBz7faaRHYvXOQD39IQ - 4.3278195311148
5 - xyz142EB29xqj5boLEDMXI0DbZ4t0l45 - 4.4139097655574
6 - xyz142EB292eJPBvdPWzqk6EycZPCu5U - 4.4528195311148
7 - xyz142EB29i4RDeXRI4gwHc8EyrWWX7x - 4.4139097655574
8 - xyz142EB29q0l54u1KX6oyTiQtVgGrJB - 4.6875
9 - xyz142EB291LMUbRzveltEEdmA4bxurX - 4.4764097655574
Mean entropy = 4.4678007421131
Time consumed per iteration: 0.11599063873291ms
Generating md5(SUUID)
Number of items represented: 340,282,366,920,928,463,463,463,374,607,431,768,211,456
- SUUID - Entropy
0 - 7a9cff898936039c308bca38614e4896 - 3.4772170014625
1 - f2640bbe2e63af0d798d20919a67001f - 3.6678377974034
2 - e912722d4ff09cc23110e38d89ef52b3 - 3.6442475629608
3 - c33cfed4dfd09fbf212e24a6cbe52b7 - 3.6678377974034
4 - 5290ebc045fde2930b297ab905cda543 - 3.5778195311148
5 - 334efcce90828f75408a6503504731c6 - 3.6556390622296
6 - 53d0dc3aa33ba26da902412bcec89cd7 - 3.6639097655574
7 - 2c701ff81578676311a807d78c18f8f2 - 3.2897170014625
8 - 29ce9c482612a2820fae10a76ff686f8 - 3.4261085007312
9 - 97b0cb7e338eff600d4a6555db62e446 - 3.757048827787
Average entropy = 3.5827382848113
Time consumed per iteration: 0.1032829284668ms
Generating Canonical UUID
Number of items represented: 340,282,366,920,928,463,463,463,374,607,431,768,211,456
- UUID - Entropy
0 - be6c96fc-34d9-4fb5-b6f6-82e7b37e6be2 - 3.6150869889135
1 - 2f260cd1-7fff-4066-804a-5af2b113acf6 - 3.6552215288595
2 - 872b0d0d-5acd-4609-88ba-38b8d5e4a3b0 - 3.6597992243145
3 - 90ba1bdb-194e-4035-9b66-2946899b4a81 - 3.541336376912
4 - 7d09dd5c-72e1-4853-8965-54dbd8514823 - 3.6706425444691
5 - 9a54bbd0-aa98-4baf-b604-fceecd0bacb3 - 3.5759228351853
6 - b3d4ab1b-ae8b-4ca4-9675-398f29c6fc48 - 3.8082708345353
7 - be4039f8-997f-4cdb-8a67-2fe2bb42e35f - 3.8082708345353
8 - 37b3d945-6f13-4a0c-b518-7962f7fe8931 - 3.9193819456464
9 - 648b88ad-dbaa-4743-93ee-f5a8ce435232 - 3.7045114597155
Average entropy = 3.6958444573086
Time consumed per iteration: 0.046086311340332ms
]]>
626
Oracle XE 10.2g e PHP 5.6 sobre Ubuntu 20 (Segundo Round) http://www.yeapf.com/wp/?p=616 Tue, 09 Mar 2021 18:57:29 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383
http://www.yeapf.com/wp/?p=616

Continuando a saga, o meu cliente precisou que o sistema dele funcionasse com pdo_oci. Isso fez com que fosse necessário instalar algumas coisas e compilar o módulo do php.

Tudo o aqui feito precisa de ser super-usuário, então a primeira coisa é fazer login como root:

sudo su -

Fiz uma pasta para que fique todo junto e seja fácil copiar as coisas para outro local depois.

cd
mkdir dev
cd dev

Obviamente que a primeira coisa a fazer é atualizar o sistema:

apt update -y && sudo apt upgrade -y

Baixei os seguintes arquivos de https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html:

oracle-instantclient-devel-10.2.0.5-1.x86_64.rpm
oracle-instantclient-basic-10.2.0.5-1.x86_64.rpm

Como o servidor é um Ubuntu (filho do Debian) precisamos a ferramenta alien para poder transformar esses arquivos .rpm em .deb

apt install alien -y

E converti os arquivos usando o alien

alien -d oracle-instantclient-basic-10.2.0.5-1.x86_64.rpm
sudo alien -d oracle-instantclient-devel-10.2.0.5-1.x86_64.rpm

Isso gerou dois arquivos que passei a instalar usando o dpkg

dpkg -i oracle-instantclient-basic_10.2.0.5-2_amd64.deb
dpkg -i oracle-instantclient-devel_10.2.0.5-2_amd64.deb

Com isso, agora temos uma pasta /usr/share/oracle/10.2.0.5/client64/ com a livraria do cliente e uma outra pasta /usr/include/oracle/10.2.0.5/client64/ com os arquivos necessários para a compilação.

Publiquei o ambiente:

export ORACLE_HOME=/usr/share/oracle/10.2.0.5/client64/
export LD_LIBRARY_PATH=$ORACLE_HOME/lib
ldconfig

Sendo que nossa versão de PHP é a 5.6.40 puxei o código fonte dela:

wget http://php.net/get/php-5.6.40.tar.bz2/from/a/mirror -O php-5.6.40.tar.bz2

Expandi o arquivo:

tar xjf php-5.6.40.tar.bz2

E preparei a pasta do módulo para compilá-lo:

cd php-5.6.40/ext/pdo_oci/
phpize

Isso produz a seguinte saída (que pode variar dependendo da versão de PHP que você está usando)

Configuring for:
PHP Api Version: 20131106
Zend Module Api No: 20131226
Zend Extension Api No: 220131226

No arquivo Makefile.global, adicionei a seguinte linha logo após INSTALL e INSTALL_DATA:

EXTRA_INCLUDES = -I/usr/include/oracle/10.2.0.5/client64

Alterei o `config.m4` adicionando 10.2 à lista das livrarias suportadas

SUPPORTED_LIB_VERS="9.0 10.1 10.2 11.1 12.1"

Alterei o script configure para reconhecer nosso php_pdo_driver.h deixando ele da seguinte forma:

if test -f $abs_srcdir/include/php/ext/pdo/php_pdo_driver.h; then
    pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $abs_srcdir/ext/pdo/php_pdo_driver.h; then 
    pdo_cv_inc_path=$abs_srcdir/ext
elif test -f $prefix/include/php/ext/pdo/php_pdo_driver.h; then 
    pdo_cv_inc_path=$prefix/include/php/ext
elif test -f /root/dev/php-5.6.40/ext/pdo/php_pdo_driver.h; then 
    pdo_cv_inc_path=/root/dev/php-5.6.40/ext/pdo/ 
fi

E (usando o cliente que foi instalado na sessão anterior) rodei o configure assim:

./configure --with-pdo-oci=instantclient,/opt/oracle_instantclient,10.2

Logo (e não tendo dado erros) compilei o módulo:

make

E procedi a instalar a extensão:

make install

Com o que ele nos devolve o local onde a extensão foi instalada:

Installing shared extensions:     /usr/lib/php/20131226/

Criei um arquivo para indicar ao php que desejo carregar a extensão compilada.

vi /etc/php/5.6/mods-available/pdo_oci.ini

Com o seguinte conteúdo:

; priority=20
extension=pdo_oci.so

E habilitei o módulo:

phpenmod pdo_oci

Finalmente reiniciei o apache:

apachectl restart

E comprovei se a extensão foi instalada e habilitada:

php -i | grep -i pdo

Devolvendo-me o seguinte resultado em tela:

PDO
PDO support => enabled
PDO drivers => oci
PDO_OCI
PDO Driver for OCI 8 and later => enabled
PWD => /root/dev/php-5.6.40/ext/pdo_oci
_SERVER["PWD"] => /root/dev/php-5.6.40/ext/pdo_oci

Evidentemente que essa extensão depende de ter a pasta /root/dev/php-5.6.40/ext/pdo_oci e caso seja necessário é possível instalar em outra pasta. Mas isso já não é o caso.

]]>
616
Oracle XE 10.2g e PHP 5.6 sobre Ubuntu 20 http://www.yeapf.com/wp/?p=601 Thu, 11 Feb 2021 02:36:18 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383
http://www.yeapf.com/wp/?p=601
Deprecated: ltrim(): Passing null to parameter #1 ($string) of type string is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/wp-db.php on line 3030

Recentemente me solicitaram colaborar em um problema de conexão entre OracleXE 10.2g e PHP 5.6

Por serem duas plataformas antigas, precisei montar meus servidores para emular tal situação.

Como na descrição não veio se era Apache ou Nginx e o comum era usar o Apache2 e me indicaram estar rodando em Ubuntu20, optei por Apache2.

Este, então, é o roteiro que segui para construir um laboratório que emulasse essa situação. Levantei dois servidores. Um para conter o Oracle XE e outro para o LAMP assim podia realizar meus testes.

O que se segue é o relato da saga.

Repare que estamos rodando sempre como root. Caso queira usar um usuário (como de fato é o certo a fazer) basta adicionar o sudo antes de cada comando.

No nosso caso é root pois os contêineres OpenVZ já rodam em ambiente seguro.

Garantir os templates do OpenVZ

Usamos OpenVZ para criarmos nossas VPS. A imagem do CentOS 7 já tínhamos, mas nos faltava a do Ubuntu. Começamos por ela.
Após uma busca, achamos este repositório:
https://plug-mirror.rcac.purdue.edu/ubuntu-cloud/releases/20.04/release/
Mas ele se mostrou inadequado.
Optamos então por usar o template do Ubuntu 16 disponível em http://mirror.yandex.ru/mirrors/download.openvz.org/template/precreated/

Criação da primeira VPS

Se bem temos nosso próprio script para criarmos as VPS preferi colocar linha por linha o que foi feito para que fique mais claro… e de quebra alguém se interessa em OpenVZ

$ vzctl create 104 --ostemplate ubuntu-16.04-x86_64 --config basic
$ vzctl set 104 --save --name lamp $ vzctl set 104 --save --onboot yes 
$ vzctl set 104 --save --hostname lamp.InovacaoSistemas.com.br 
$ vzctl set 104 --save --ipadd 192.168.1.104/24 
$ vzctl set 104 --save --searchdomain InovacaoSistemas.com.br
$ vzctl set 104 --save --nameserver 1.1.1.1 --nameserver 8.8.4.4 
$ vzctl set 104 --save --cpus 2 
$ vzctl set 104 --save --ram 512M 
$ vzctl set 104 --save --swap 1G 
$ vzctl set 104 --save --diskspace 20G 
$ vzctl start 104 
$ vzctl exec 104 passwd 
$ vzctl exec 104 apt-get update -y

Atualização para Ubuntu 20.04

Após instalarmos o Ubuntu 16, procedemos com um upgrade para termos um 20.04 rodando o do-release-upgrade.
O problema é que como escolhemos a imagem mínima, tivemos que primeiro instalar a ferramenta e logo a seguir atualizar o sistema.

$ apt install ubuntu-release-upgrader-core
$ apt update -y
$ apt upgrade -y

Primeiro atualizamos de 16.04 para 18.04


$ do-release-upgrade

E mais uma vez para irmos de 18.04 para 20.04


$ apt update -y
$ apt upgrade -y
$ do-release-upgrade --mode=server --quiet

Como é uma atualização de uma instalação nova, respondemos que sim a todas as perguntas…. como se fossemos usuários Windows.

Uma vez feito isso, reiniciamos a máquina e testamos algumas coisas para ver se estava tudo ok.

Como nos pode ser útil ter um Ubuntu 20, decidimos guardar uma cópia na forma de template.

$ vzctl stop 104
$ cd /vz/private/104
$ tar -cvzpf /vz/template/cache/ubuntu-20.04-server-amd64.tar.gz .

Mas isso não faz parte do roteiro. Foi apenas um agradável desvio.

Criação da segunda VPS

A segunda máquina é uma CentOS 7 mas a criamos usando o script e a chamada ficou assim:

$ ./createCentos7VM.sh 102 oracleXE inovacaosistemas.com.br

Instalando o Oracle 10.2 XE no CentOS

Dentro do CentOS realizamos as seguintes operações:

$ yum install epel-release
$ yum update -y
$ yum install libaio bc flex -y
$ yum install install glibc.i686
$ wget http://ftp.cs.stanford.edu/pub/fedora/6/i386/oracle-xe-10.2.0.1-1.0.i386.rpm
$ rpm -ivh oracle-xe-10.2.0.1-1.0.i386.rpm
$ /etc/init.d/oracle-xe configure

No arquivo /etc/bashrc adicionamos uma chamada ao script que constrói o ambiente dentro do qual os comandos do oracle podem funcionar como a seguir

. /usr/lib/oracle/xe/app/oracle/product/10.2.0/server/bin/oracle_env.sh

(não esqueça do ponto seguido de um espaço no inicio)

Liberamos algumas portas no firewall assim

$ firewall-cmd --permanent --zone=public --add-port=8080/tcp
$ firewall-cmd --permanent --zone=public --add-port=1521/tcp
$ firewall-cmd --reload

Feito isso, criamos a partir do nosso micro um túnel assim:

$ ssh root@192.168.1.102 -L8080:localhost:8080

Isso nos permitiu abrir o navegador localmente com o seguinte endereço:

http://localhost:8080/apex

Usando o APEX, criamos um usuário como mostramos nesta figura:

Esse usuário e senha é o que usaremos mais adiante para testarmos nossa conexão.

Instalando o Apache2 e o PHP5.6 no Ubuntu

Instalamos o apache2 da seguinte maneira

$ apt get install apache2 -y

Como não nos interessa problemas de domínio, segurança e coisas parecidas, deixamos ela como está.

Já instalar o php5.6 requer um pouco mais de voltas. Mais ou menos com quando um cachorro vai deitar.

$ apt install software-properties-common 
$ add-apt-repository ppa:ondrej/php
$ apt update -y
$ apt install -y php5.6

Criamos um pequeno script para nos mostrar a situação em /var/www/html chamado info.php com o seguinte conteúdo:

<?php
  phpinfo();

E abrimos ele no navegador para visualizar se o PHP estava rodando e em qual versão

http://192.168.1.104/info.php

Reiniciamos o servidor para termos certeza que tudo está ok.

Instalando o cliente Oracle no Ubuntu

Fizemos download do basic-10.2.0.5.0-linux.zip e sdk-10.2.0.5.0-linux.zip deste endereço: https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html

E depois o instalamos

$ unzip basic-10.2.0.5.0-linux-x64.zip
$ mkdir /opt/oracle_instantclient
$ mv instantclient_10_2/* /opt/oracle_instantclient/
$ unzip ../sdk-10.2.0.5.0-linux.zip
$ mv instantclient_10_2/* /opt/oracle_instantclient/
$ cd /opt/oracle_instantclient/
$ ln -s libclntsh.so.10.1 libclntsh.so
$ apt-get install php5.6-dev -y
$ apt-get install libaio-dev -y
$ apt-get install php5.6-common php5.6-xml php5.6-cli -y
$ apt-get install php-pear -y
$ pecl channel-update pecl.php.net
$ pecl install oci8-2.0.12

Na hora em que pergunte onde está o cliente instantclient, devemos indicar instantclient,/opt/oracle_instantclient

Dando tudo certo com a compilação, devemos adicionar o oci8.so aos php.ini da seguinte forma:

$ echo "extension=oci8.so" >> /etc/php/5.6/apache2/php.ini
$ echo "extension=oci8.so" >> /etc/php/5.6/cli/php.ini

Outra coisa que precisamos fazer é indicar onde ficou a livraria do instant-client como segue:

$ echo /opt/oracle_instantclient/ > /etc/ld.so.conf.d/oracle-instantclient.conf
$ ldconfig

E finalmente reiniciamos o apache2 assim:

$ apachectl restart

Navegando novamente no http://192.168.1.104/info.php podemos confirmar que o OCI está configurado como mostra a figura

Finalmente, testamos nossa conexão com um pequeno script colocado em /var/www/html sob o nome testar-conexao-oracle.php com este conteúdo:

<?php
$conn = oci_connect("teste", "abc123", "192.168.1.102/XE");
if ($conn) {
echo "Conexão realizada com sucesso\n";
} else {
echo "Erro na conexão com o banco de dados\n";
}

E testamos o mesmo desde a linha de comando:

$ php testar-oci8.php

Se tudo ocorreu bem ele nos mostrará que a conexão deu certo.

Podemos também testar usando o navegador:

http://192.168.1.104/testar-oci8.php

Bem, com isso chegamos ao fim do problema da conexão com vanilla PHP.

]]>
601
Criando um ambiente de desenvolvimento LAMP http://www.yeapf.com/wp/?p=583 Thu, 05 Mar 2020 18:52:09 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383
http://www.yeapf.com/wp/?p=583 LAMP é um acrônimo representando Linux, Apache, MySQL e PHP

Um ambiente LAMP nos dá os elementos básicos para poder programar.

Como o alvo é programar sobre um servidor e não sobre ambiente Desktop, a instalação será sem GUI mas fique livre para faze-lo. Eu mesmo não tenho recursos tão abundantes assim para pôr interface gráfica em um servidor que vou controlar via ssh.

Escolhemos Ubuntu por ser o Linux mais simples de instalar e usar no dia a dia do desenvolvedor. Para produção costumamos colocar CentOS que é mais leve porém às vezes mais nojentinho de configurar.

Se você já tem uma VM com Ubuntu, pode pular para “Instalando LAMP” lá no final

  1. Baixe a última versão estável do Ubuntu

    No momento de escrever este artigo, estava na 18.04.4 LTS (Sempre escolha as versões 04 que tem maior durabilidade garantida pela Cannonical)

    https://ubuntu.com/download/server

  2. Crie uma máquina virtual

    a. Verifique se o local de armazenamento existe

    No meu caso, eu deixo todas as máquinas virtuais em uma pasta chamada ‘VirtualBoxes’ alocada na raiz do usuário; isto é: /home/esteban/VirtualBoxes. Então, e não tem uma pasta assim e quer cria-la faça como segue:

    $ mkdir ~/VirtualBoxes
    b. Crie sua máquina virtual usando o seguinte comando:
    $ VBoxManage createvm --name MeuLAMP --ostype Debian_64 --register --basefolder ~/VirtualBoxes/ 

    O VBoxManage vai responder alguma coisa assim:

    Virtual machine 'MeuLAMP' is created and registered.
    UUID: 3156aee4-8a2e-46dd-ae69-54533c78ff5f
    Settings file: '/Users/estebandortta/VirtualBoxes/MeuLAMP/MeuLAMP.vbox'
    c. Modifique ela para seus parâmetros mínimos.

    No caso 512MB de RAM, IOAPIC ligado e uma interface de rede em modo bridge (ponte). Repare que no meu caso, a placa de rede que vai ser usada como ponte é a chamada en1. Por isso que usei ela. No seu caso isso é diferente.

    Para obter uma lista das placas conectadas na sua máquina, pode usar o seguinte comando:

    $ ifconfig | grep "^[a-z0-9]*\:" | awk '{ print $1 }'

    Uma vez determinado o nome, pode proceder como segue:

    $ VBoxManage modifyvm MeuLAMP --ioapic on
    $ VBoxManage modifyvm MeuLAMP --memory 512 --vram 128
    $ VBoxManage modifyvm MeuLAMP --nic1 Bridged  --bridgeadapter1 en1

    Estes comandos, se bem executados, não devolvem coisa alguma na tela.

    d. Agora vamos adicionar um disco

    Ele será de tamanho típico (70GB) para este tipo de serviço mas pode ser menor ou maior. Depende de sua capacidade. Não recomendo abaixo de 40GB. Repare que meu download ficou em ~/Downloads/OS/Linux/ubuntu-18.04.3-live-server-amd64.iso então modifique conforme necessário.

    $ VBoxManage createhd --filename ~/VirtualBoxes/MeuLAMP/MeuLAMP_DISK.vdi --size 70000 --format VDI
    $ VBoxManage storagectl MeuLAMP --name "SATA Controller" --add sata --controller IntelAhci
    $ VBoxManage internalcommands sethduuid ~/VirtualBoxes/MeuLAMP/MeuLAMP_DISK.vdi
    $ VBoxManage storageattach MeuLAMP --storagectl "SATA Controller" --port 0 --device 0 --type hdd --medium  ~/VirtualBoxes/MeuLAMP/MeuLAMP_DISK.vdi
    $ VBoxManage storagectl MeuLAMP --name "IDE Controller" --add ide --controller PIIX4
    $ VBoxManage storageattach MeuLAMP --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium ~/Downloads/OS/Linux/ubuntu-18.04.3-live-server-amd64.iso
    $ VBoxManage modifyvm MeuLAMP --boot1 dvd --boot2 disk --boot3 none --boot4 none
    e. Configuramos acesso remoto

    O configuramos via vrde para podermos lidar com a tela dela no inicio e se alguma coisa acontece com ela durante o uso posterior. O porto (no caso 10004) é da sua escolha apenas use um que não exista.

    $ VBoxManage modifyvm MeuLAMP --vrde on
    $ VBoxManage modifyvm MeuLAMP --vrdemulticon on --vrdeport 10004
    f. Finalmente, inicie sua máquina para poder configura-la
    $ VBoxManage startvm MeuLAMP

    Lembre que posteriormente, podemos usar este comando para iniciar ela “sem-cabeça”. Ou seja, sem interface. Com isso vc poupará alguns recursos de CPU, GPU, RAM, etc. Usamos isso em produção.

    $ VBoxHeadless --startvm MeuLAMP
  3. Coisas a serem feitas durante a instalação

    a. Escolha a partição que ocupa o disco inteiro e sem LVM.

    Em produção é o contrário. Ou seja, particionamos o disco diferente e usamos LVM que nos permite adicionar mais discos e não apenas mudar o tamanho.

    b. Configure seu usuário.

    Este é um usuário comum mas com direitos administrativos. Não esqueça a senha mas também não a anote no post-it. Chegado o caso anote ela na manga da camisa. A mulher vai se encarregar de fixar ela na sua memória.

    b. Não esqueça de instalar o SSH (Ele vai oferecer OpenSSH logo após particionar o disco)

    É importante ter seu SSH instalado pois é por meio dele que você vai acessar sua máquina. Sim, você não está sendo treinado para ser um gnutellinha da vida. Um acesso SSH te libera da exigência brutal de ter uma banda muito larga já que os comandos e seus retornos são textuais.

    c. Deixe o restante como está.

    Se precisar de proxy, indique no momento adequado.

    d. Aguarde até o fim.

    Ele vai demorar baixando as atualizações de segurança. Deixe rolar. Melhor agora do que depois.

    c. Caso a atualização der problemas escolha “Cancel Update and Reboot”
  4. Coisas a serem feitas após a instalação

    Quando chegue ao final da instalação, o sistema instalado vai reiniciar. Observe que ele solicita para remover o disco de instalação. Como colocamos o disco de instalação como “CD-ROM”, o instalador já se encarregou de “ejetar” o mesmo. É só reiniciar (dando ENTER na VM) e boa.

    Assim que a máquina reinicie, ingresse nela usando seu usuário e senha cadastrado no primeiro passo.

    Na primeira vez, ele vai estar ainda configurando algumas coisas, então tenha paciência.

    A única coisa que interessa dessa entrada, é pegar o IP dela para poder acessa-la via SSH.

    Obtemos esse IP usando o comando ifconfig da seguinte maneira:

    esteban@meulamp:~$ ifconfig

    Ele nos devolverá alguma coisa assim:

    enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
           inet 192.168.0.152  netmask 255.255.255.0  broadcast 192.168.0.255
           inet6 fe80::a00:27ff:fe07:8f8b  prefixlen 64  scopeid 0x20<link>
           ether 08:00:27:07:8f:8b  txqueuelen 1000  (Ethernet)
           RX packets 855  bytes 642531 (642.5 KB)
           RX errors 0  dropped 2  overruns 0  frame 0
           TX packets 243  bytes 30082 (30.0 KB)
           TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
           inet 127.0.0.1  netmask 255.0.0.0
           inet6 ::1  prefixlen 128  scopeid 0x10<host>
           loop  txqueuelen 1000  (Local Loopback)
           RX packets 104  bytes 8136 (8.1 KB)
           RX errors 0  dropped 0  overruns 0  frame 0
           TX packets 104  bytes 8136 (8.1 KB)
           TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

    Mas desse trambolho todo só nos interessa o IP da primeira placa. A ‘lo’ é uma placa virtual que existe em todo linux para que a pilha TCP/IP funcione. (Lembre que X11 é um servidor que roda no seu próprio micro e sobre TCP/IP. Assim como ele há um monte de programas que esperam que vc tenha uma pilha TCP/IP ativa. Por isso ela está embutida).

    Então, simplificamos para o seguinte comando para obtermos o IP da máquina:

    esteban@meulamp:~$ ifconfig | grep -w inet | grep -vw 127 | awk '{ print $2 }'

    Com este comando mais simples, direto, eficiente, bonito, fácil de lembrar, obtemos apenas o IP da máquina. No meu caso a saída se resume a isto aqui:

    192.168.0.152

    Agora, devemos reconhecer que é um saco ter que abrir a máquina virtual para saber qual IP que ele pegou. Por outro lado, precisamos de essa informação para trabalhar. Comigo acontece de que geralmente não posso deixar ela com IP fixo já que uso ela em diferentes redes.

    Uma forma de solucionar isso, é que a própria máquina mostre o IP que pegou na tela antes do login. Desta forma, apenas abrir a tela da VM (Lebre que vamos usar sem tela) já nos mostra esse IP. (Eu não sei vocês, mas eu esqueço dos IPs fixos tb, então eu coloco em tudo quanto é máquina)

    Para conseguir isso, vamos modificar o arquivo /etc/issue que é o arquivo que é mostrado no fim do processo de inicialização e logo antes do login.

    Como minha placa chama-se enp0s3 (Detesto esses nomes novos, gostava de quando eram eth0 por exemplo) o meu arquivo /etc/issue fica assim:

    Ubuntu 18.04.4 LTS n l
    enp0s3: 4{enp0s3}
    ------------------------------------------

    Ao reiniciar a máquina virtual, lá estará a informação que preciso para poder trabalhar.

  5. Configurando seu acesso via SSH

    Usar uma máquina virtual via tela é pedir para sofrer. Ela é mais lenta, não tem jeito.

    Mesmo se instalou a GUI (como é o caso de Windows Desktop por exemplo que não tem como instalar sem interface gráfica) o melhor é o acesso remoto. Claro, há exeções, mas a regra é essa.

    Bem, antes de se apaixonar pelo ssh, você tem que ser triducidado por ele.

    Se seu ambiente é Windows, um cliente ssh potável é o PuTTY (https://putty.org) mas o que eu mais gosto é Cygwin (https://www.cygwin.com). Agora, com isso de que o Windows10 já vem com bash (e Ubuntu) embarcado, imagino que o melhor seja usar a opção que vem embarcada.

    Eu vou supor que está usando Linux, Cygwin ou bash embarcado.

    a. Acesse sua máquina virtual desde a linha de comandos da sua máquina. No meu caso fica assim:
    $ ssh esteban@192.168.0.152

    Por ser a primeira vez, o meu bash responde assim:

    The authenticity of host '192.168.0.152 (192.168.0.152)' can't be established.
    ECDSA key fingerprint is SHA256:poNetFdUSSEYn8tH2Mu7Vy7NLdq25lFaCJ449rt2bjw.
    Are you sure you want to continue connecting (yes/no)?

    Ao que eu respondo que sim em inglês fluente. Ou seja “yes” e não apenas “y”

    Com isso o servidor fica registrado na lista de alvos conhecidos pelo ssh

    Logo apósi digito a senha que registrei na hora da instalação e pronto, estou nele.

    Mas vamos sair, porque -não sei vocês- mas eu detesto ter que lembrar de senhas e tal.

    Para sair, digitamos exit ou usamos ctrl-d que dá na mesma.

    SÓ CONTINUE SE VOLTOU NA SUA MÁQUINA MÃE

    b. Tem ou não um par de chaves na sua máquina mãe?

    Pode acontecer que você não tenha um par de chaves criadas. Para verificar se tem, use o seguinte comando:

    $ ls ~/.ssh/*

    Se ele mostra dois arquivos id_rsa e id_rsa.pub, você já tem as chaves criadas e não há de que se preocupar (a não ser, claro que tenha criado as chaves com senha e as tenha esquecido)

    Se ele mostrar alguma coisa parecida com a imagem abaixo é porque você não tem o par de chaves:

    ls: cannot access '/home/esteban/.ssh/': No such file or directory

    Caso, então, tenha que criar esse par de chaves, o fazemos usando o seguinte comando:

    $ ssh-keygen

    Deixe que o demônio do usuário Windows entre em você e dé ENTER até o final. Dessa forma criará um par de chaves que não precisam senha para serem usadas. (Em produção você coloca senha nelas)

    A saída fica mais ou menos assim:

    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/esteban/.ssh/id_rsa): 
    Created directory '/home/esteban/.ssh'.
    Enter passphrase (empty for no passphrase): 
    Enter same passphrase again: 
    Your identification has been saved in /home/esteban/.ssh/id_rsa.
    Your public key has been saved in /home/esteban/.ssh/id_rsa.pub.
    The key fingerprint is:
    SHA256:1h2/DAEBwxLLwiKYFSyY3FSiFtWRAvO1t8snCgGxCAY esteban@meulamp
    The key's randomart image is:
    +---[RSA 2048]----+
    |EOB=o++oo.o.     |
    |O+O+o+o... .     |
    |=*..+.oo    o    |
    |.... .. .. . +   |
    |   .   .S . o .  |
    |    . ...    o . |
    |   .   + .    o  |
    |    . . o        |
    |     .           |
    +----[SHA256]-----+
    c. Copie sua chave pública para a VM

    Para poder facilitar o acesso via SSH, você agora vai copiar sua chave pública para a máquina que criou. No meu caso fica assim:

    $ ssh-copy-id esteban@192.168.0.152

    E ele produzirá uma saída semelhante a esta

    /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/Users/estebandortta/.ssh/id_rsa.pub"
    /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
    /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
    esteban@192.168.0.152's password: 
    
    Number of key(s) added:        1
    
    Now try logging into the machine, with:   "ssh 'esteban@192.168.0.152'"
    and check to make sure that only the key(s) you wanted were added.

    Eu digitei a senha da VM quando me pediu. Se você criou seu par de chaves com senha, vai pedir essa senha tb. Ai vc vai lembrar o porque que eu disse para colocar sem senha.

    Bem, a partir deste momento entrar na sua máquina virtual via ssh será tão simples como fazer

    $ ssh esteban@192.168.0.152

    E ele deve ir sem pedir senha (a não ser que o par de chaves…bla bla bla)

  6. Instalando o LAMP

    Entraremos na virtual. Use o comando similar ao seguinte

    $ ssh esteban@192.168.0.152
    a. Instale o básico

    O que é o básico no LAMP?

    Bom, sendo que está no Linux, só falta AMP (Apache, MySQL e PHP)

    Existem pacotes prontos que faremos bem em evitar pois buscamos aprender o que é – de fato – importante.

    Primeiro atualizaremos a base instalada (isso pode levar um tempinho a primeira vez)

    esteban@meulamp:~$ sudo apt-get update -y

    Ele vai pedir a senha de usuário para poder fazer sudo

    Em lugar do MySQL vamos instalar o MariaDB. (MariaDB é um fork de MySQL que o criador de MySQL fez quando abandonou a Oracle. O criador do MySQL tinha ido para a Oracle contando com que a Oracle ia manter seus tentáculos longe e manter o MySQL aberto. Como isso não aconteceu, ele foi embora. Perdeu o nome MySQL mas o software é o mesmo… e manteve a dignidade que – nos tempos que correm – digamos que é importante)

    esteban@meulamp:~$ sudo apt-get install apache2 php mariadb-server mariadb-client php-mysql -y
    
    Dependendo de sua distribuição, pode ser que o apache não esteja configurado para iniciar junto com o sistema. Habilite o apache e inicie ele com estes dois comandos:
    
    esteban@meulamp:~$ sudo systemctl enable apache2
    esteban@meulamp:~$ sudo systemctl start apache2
    

    Dessa forma, quando você reiniciar sua máquina, o apache estará funcionando mas para continuar agora, ele também estará funcionando.

    b.Configure o acesso ao banco de dados

    Uma vez instalado, é bom configurar o banco de dados. Basicamente precisamos que ele seja seguro o suficiente como para trabalhar, mas tb que não encha o saco com muitas exigências.

    esteban@meulamp:~$ sudo mysql_secure_installation

    Assim que ele é instalado, o root está sem senha. Então quando perguntado, crie uma senha para root.

    • Depois remova os usuários anónimos
    • Permita acesso remoto pelo root (em produção é o contrário)
    • Remova a base de testes
    • Recarregue sua tabela de privilegios

    Pronto, seu MariaDB está configurado. Agora reinicie ele:

    esteban@meulamp:~$ sudo systemctl restart mariadb

    E teste o seu acesso local:

    esteban@meulamp:~$ mysql -u root -p

    Se tudo deu certo, você vai ter uma tela parecida com esta:

    Welcome to the MariaDB monitor.  Commands end with ; or g.
    Your MariaDB connection id is 35
    Server version: 10.1.44-MariaDB-0ubuntu0.18.04.1 Ubuntu 18.04
    
    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
    
    Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.
    
    MariaDB [(none)]> Bye

    Mas, pode ser que sua combinação de Ubuntu/MariaDB esteja meio louca. Geralmente o problema está com o protocolo de autenticação. Nesse caso ele vai mostrar uma saída como a seguinte:

    esteban@meulamp:~$ mysql -u root -p
    Enter password: 
    ERROR 1698 (28000): Access denied for user 'root'@'localhost'

    Se tiver esse problema você pode proceder da seguinte forma primeiro para confirmar o erro e depois para corregi-lo:

    esteban@meulamp:~$ sudo mysql
    MariaDB [(none)]> use mysql;
    MariaDB [mysql]> select user, plugin from user;

    Ele vai mostrar para você uma saida com esta que serve para identificar se esse é seu problema:

    +------+-------------+
    | user | plugin      |
    +------+-------------+
    | root | unix_socket |
    +------+-------------+
    1 row in set (0.00 sec)

    Corrigimos isso assim:

    MariaDB [mysql]> update user set plugin='mysql_native_password' where user='root';
    MariaDB [mysql]> flush privileges;
    MariaDB [mysql]> exit

    Agora, desde seu usuário comum, você deve ser capaz de entrar no mysql localmente

    esteban@meulamp:~$ mysql -u root -p

    Feito isso, volte na sua máquina mãe e tente o acesso ao servidor de banco de dados

    esteban@meulamp:~$ exit
    logout
    Connection to 192.168.0.152 closed.
    $ mysql -u root -p -h 192.168.0.152
    Enter password: 
    ERROR 2003 (HY000): Can't connect to MySQL server on '192.168.0.152' (61)

    No meu caso, esse é o erro que dá. Isso está dizendo que o servidor não está ouvindo no IP indicado.

    Assim que voltamos à VM e corrigimos a configuração do MariaDB

    $ ssh esteban@192.168.0.152
    esteban@meulamp:~$ sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf

    Procure pela linha que diz

    bind-address = 127.0.0.1

    e substitua pelo seguinte

    bind-address = *

    Agora reinicie o servidor

    esteban@meulamp:~$ sudo systemctl restart mariadb

    Volte à sua maquina mãe (gosto de chama-la assim… parece com ‘nave mãe’ ao final das contas somos como que alienigenas invadindo as VM da vida)

    esteban@meulamp:~$ logout
    Connection to 192.168.0.152 closed.
    [estebandortta@Estebans-MacBook-Pro ~] mysql -u root -p -h 192.168.0.152
    Enter password: 
    ERROR 1130 (HY000): Host '192.168.0.142' is not allowed to connect to this MariaDB server

    Repare que o erro mudou. Agora nos está dizendo que o nosso host (no caso 192.168.0.142 que é o IP da minha máquina mãe) está impedido de acessar.

    Voltamos à VM e – usando nosso direito de acesso ao banco lá dentro – corrigimos isso assim:

    $ ssh esteban@192.168.0.152
    esteban@meulamp:~$ mysql -u root -p

    E uma vez dentro do mysql fazemos assim:

    MariaDB [(none)]> CREATE USER 'root'@'192.168.%' IDENTIFIED BY 'tr3co';
    Query OK, 0 rows affected (0.00 sec)
    
    MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.%';
    Query OK, 0 rows affected (0.00 sec)
    
    MariaDB [(none)]> FLUSH PRIVILEGES;
    Query OK, 0 rows affected (0.00 sec)
    
    MariaDB [(none)]> exit

    Com isso criamos um novo usuário também chamado root mas com a senha tr3co que pode acessar este servidor desde qualquer micro da rede 192.168.x.x (Repare o uso do coringa ‘%’)

    Voltamos à máquina mãe e testamos o acesso.

    esteban@meulamp:~$ exit
    logout
    Connection to 192.168.0.152 closed.
    
    $ mysql -u root -ps3nha -h 192.168.0.152
    Welcome to the MariaDB monitor.  Commands end with ; or g.
    Your MariaDB connection id is 7
    Server version: 10.1.44-MariaDB-0ubuntu0.18.04.1 Ubuntu 18.04
    
    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
    
    Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.
    
    MariaDB [(none)]>
    c. Alterando as configurações do usuário

    É necessário que o usuário comum possa escrever na pasta /var/www/html

    A forma mais fácil disso é fazer um sudo chmod -fR 0777 /var/www/html que é o análogo a colocar a saida do vaso direto no ralo do chuveiro. Funciona.

    O certo mesmo é fazer com que o usuário comum (que tb é administrativo) consiga escrever na pasta /var/www/html

    A primeira coisa a fazer é verificar em que grupo o apache2 trabalha. O seguinte comando faz isso:

    esteban@meulamp:~$ ps aux | grep apache | awk '{ print $1 }' | grep -v "root|esteban" | uniq

    No meu caso ele me devolve www-data. Para eu, usuário comum, poder escrever nas pastas desse grupo, devo pertencer ao mesmo.

    Você pode verificar os direitos que seu usuário comum tem da seguinte forma:

    esteban@meulamp:~$ id esteban
    uid=1000(esteban) gid=1000(esteban) groups=1000(esteban),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lxd)

    Como você pode observar, o meu usuário comum não pertence ao grupo www-data. Adicionamos ele ao grupo com o seguinte comando:

    esteban@meulamp:~$ sudo usermod -a -G www-data esteban

    E podemos verificar com o comando id que de fato ele foi adicionado:

    esteban@meulamp:~$ id esteban
    uid=1000(esteban) gid=1000(esteban) groups=1000(esteban),4(adm),24(cdrom),27(sudo),30(dip),33(www-data),46(plugdev),108(lxd)

    Só que se você for ver, ainda não pode criar arquivos na pasta /var/www/html:

    esteban@meulamp:~$ touch /var/www/html/info.php 
    touch: cannot touch '/var/www/html/info.php': Permission denied

    A forma mais limpa de resolver isto é se apropriando da pasta /var/www/html:

    esteban@meulamp:~$ sudo chown esteban /var/www/html
    esteban@meulamp:~$ sudo chgrp www-data /var/www/html

    Uma vez feito isso, você pode criar o arquivo /var/www/html/info.php com o seguinte conteúdo para comprovar o correto funcionamento e instalação de tudo:

    <?php
     phpinfo();
    ?>

    Proceda a testar a sua configuração solicitando ao apache que processe esse arquivo e mostre a saida na tela. Ou seja, navegue.

    http://192.168.0.152/info.php

    Se tudo ocorreu bem, tem que aparecer uma lista com as configurações atuais do apache, o php e o mysql.

  7. Criando o primeiro programa

    Bom, se tudo deu certo, é hora de criarmos o primeiro programa.

    Mas para que o teste seja completo, vamos criar primeiro um banco de dados

    esteban@meulamp:~$ mysql -u root -p
    Welcome to the MariaDB monitor.  Commands end with ; or g.
    Your MariaDB connection id is 7
    Server version: 10.1.44-MariaDB-0ubuntu0.18.04.1 Ubuntu 18.04
    
    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
    
    Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.
    
    MariaDB [(none)]> create database meuTeste;
    Query OK, 1 row affected (0.00 sec)
    
    MariaDB [(none)]> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | meuTeste           |
    | mysql              |
    | performance_schema |
    +--------------------+
    4 rows in set (0.00 sec)

    Uma vez criado o banco meuTeste (que por enquanto não tem tabelas) vamos escrever nosso primeiro programa.

    esteban@meulamp:~$ nano /var/www/html/testar-conexao.php

    Digitando o seguinte lá dentro:

    <?php
     $con = mysqli_connect("localhost:3306", "root", "czyhnp");
     if ($con) {
       $db = mysqli_select_db("meuTeste")
       echo "Ok";
     } else {
       echo "Impossível conectar";
     }

    Confirmamos que tudo esteja bem com ele usando o seguinte comando:

    esteban@meulamp:~$ php -l /var/www/html/testar-conexao.php 

    Corrigimos os erros (se você estava copiando-colando tem um erro) usando o nano e o testamos pedindo para o apache2 usar seu pre-processador, passar para o php, este realizar o serviço, devolver seu resultado numa pipe textual, e o apache2 devolver para a conexão para que o navegador renderize isso perante nós. Simplificando: navegue

    http://192.168.0.152/testar-conexao.php

  8. Finalmente, reinicie

    Com isso tudo pronto, reinice seu servidor e teste novamente para ver que tudo esteja ok

    esteban@meulamp:~$ sudo reboot

    Se os passos foram seguidos, tudo tem que continuar funcionando ok.

    Lembre apenas que da próxima vez, vc pode levantar sua maquina virtual apenas usando a opção HeadLess

    $ VBoxHeadless --startvm MeuLAMP
]]>
583
Gerando dados ficticios para testes http://www.yeapf.com/wp/?p=501 Wed, 12 Dec 2018 16:40:16 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383
http://www.yeapf.com/wp/?p=501 Convenhamos que nem sempre é fácil gerar uma boa quantidade de dados como para testar um sistema apenas com o uso da imaginação. Não que a imaginação não seja fertil, mas sim que cansa andar imaginando apenas sobre um único assunto. Faz parte da natureza da imaginação interessar-se por coisas alheias ao foco em que queremos que ela fique… seria mais ou menos como a vida de um artista e daquele que vive de vender sua produção musical: o primeiro DVD realmente é bacana, o segundo é uma tentativa pífia de manter o fluxo de dinheiro e para o terceiro tudo quanto é tesão não existe mais.

Bom, ilustrações fonográficas à parte, quando se trata de um sistema precisamos de gerar vários regitros com qualquer tipo de informação contanto ele preencha certos requisitos. Por exemplo: o cpf tem que ser válido.

Incluimos no YeAPF 0.8.61-170 uma pequena função que pode fazer a diferença na hora de criar esses dados: fillFieldsWithJunk()

Você pode usa-la para criar apenas um único campo ou um registro inteiro.

Mas um exemplo pode ser mais util que mil palavras. Digamos que quero gerar um registro com dados aleatórios. Isto (que chamarei de testar-geracao-dados.php) resolve:

require_once "yeapf.php";
$campos = array(     
  array(
      "id" => "nome",
      "type" => "text",
      "className" => "male name",
      "maxlength" => "25"
    ),
    array(
      "id" => "cpf",
      "type" => "text",
      "className" => "cpf"
    ),
    array(
      "id" => "endereco",
      "type" => "text",
      "maxlength" => "70"
    ),
    array(
      "id" => "site",
      "type" => "url"
    ),
    array(
      "id" => "telefone",
      "type" => "tel"
    ),
    array(
      "id" => "email",
      "type" => "email"
    ),
    array(
      "id" => "cep",
      "type" => "text",
      "className" => "cep-cliente"
    )
  );
/* gero os dados */
$dados = fillFieldsWithJunk($campos);
/* imprimo na tela */
print_r($dados);

Agora, desde a linha de comando executamos ele usando o php

$ php testar-geracao-dados.php

Pronto, cada vez que rodemos, obteremos um novo conjunto de dados.

O seguinte exemplo geraremos esses dados em JSON. Pelo bem da simplicidade apenas mostraremos as linhas modificadas (que são as últimas)

/* gero os dados */
$dados = fillFieldsWithJunk($campos);
/* imprimo na tela como JSON */
echo json_encode($dados);

E finalmente, faremos um teste preenchedo 2378 registros de uma tabela que chamaremos clientes (foje ao escopo deste artigo mostrar criação de tabelas, conexão com o banco de dados, etc)

Novamente, mostraremos as linhas modificadas que são as últimas:

$quantidadeRegistros = 2378;
while ($quantidadeRegistros-->0) {
  $dados = fillFieldsWithJunk($campos);
  $sql=save_form_sql($dados, "clientes", "id");
  db_sql($sql);
}

Pronto, seu banco já está cheio de…. bom, o que fillFieldsWithJunk() conseguir gerar.

 

]]>
501
Node + Electron + YeAPF http://www.yeapf.com/wp/?p=454 Fri, 03 Aug 2018 20:16:54 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383
http://www.yeapf.com/wp/?p=454 Deprecated: ltrim(): Passing null to parameter #1 ($string) of type string is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/wp-db.php on line 3030
Saladas são boas. Por isso o título mistura três coisas que já sozinhas são boas. O node te permite escrever aplicativos do lado do servidor ou do cliente usando a mesma linguagem: JavaScript. Neste vamos usa-lo para criar um aplicativo do lado cliente com técnicas de web (HTML5, CSS3 e JS6). Esta aproximação nos permite […]]]>

Deprecated: ltrim(): Passing null to parameter #1 ($string) of type string is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/wp-db.php on line 3030
Saladas são boas. Por isso o título mistura três coisas que já sozinhas são boas.

O node te permite escrever aplicativos do lado do servidor ou do cliente usando a mesma linguagem: JavaScript. Neste vamos usa-lo para criar um aplicativo do lado cliente com técnicas de web (HTML5, CSS3 e JS6). Esta aproximação nos permite ter acesso ao hardware local, coisa que com o navegador é impossível (e esperemos que continue assim)

Já o ElectronJS nos permite empacotar isso tudo e distribuir em multiplataforma. Ou seja, o mesmo código rodando em Windows, Linux, OSX, etc. Seria bom dar uma olhada aqui: https://electronjs.org/docs/tutorial/first-app

YeAPF uniformiza o jeito de acessar a informação, promove melhores padrões de desenvolvimento e permite integrar seu aplicativo com outros.

Aqui há um caminho apenas. Você pode escolher outra forma mas mostramos esta por ser a mais simples – desde nosso ponto de vista – de criar um aplicativo.

Partimos da base que tem o NPM instalado assim como as ferramentas do YeAPF.

Há duas formas de fazer isto. Use a que lhe seja mais conveniente.

Primeira forma: Instalando o YeAPF no final

$ cd ~/Documents
$ mkdir MeuProjeto
$ cd MeuProjeto
$ npm init

Depois modifique o package.json para que main aponte para “main.js”.

Pode tb deixar do jeito que está que electron vai procurar por “index.js”

Depois instale o electron nessa pasta

$ npm install --save-dev electron

Agora coloque o aplicativo de exemplo do YeAPF nele

$ yapp ./ --create --appType electron

Finalmente rode o aplicativo

$ npm start

 

Segunda forma: Começando pelo YeAPF

O mesmo efeito anterior, pode ser obtido com a seguinte sequencia de comandos:

$ cd ~/Documents
$ yapp MeuSegundoProjeto --create --appType electron
$ cd MeuSegundoProjeto
$ npm install
$ npm start

Como proceder daqui em diante?

Se tudo deu certo, você terá um outro aplicativo aberto mostrando o conteúdo do index.html que foi colocado lá pelo YeAPF.

Mantendo ele aberto, você pode modificar o index.html e recarregar o aplicativo sem fecha-lo (ctrl-R, F5, etc) ao final das contas o que vc está rodando é um Chrome.

Se um arrepio correu pelas suas costas, é que vc já entendeu o potencial.

Se nada disso lhe deu nem tchum, talvez não saiba o complicado que é produzir software para mais de uma plataforma e – pior – que rode na primeira. Com um pouco mais de tempo chegará a observar a importância disto.

]]>
454
Imprimindo diretamente no porto LP usando ElectronJS http://www.yeapf.com/wp/?p=441 http://www.yeapf.com/wp/?p=441#comments Wed, 25 Jul 2018 20:32:19 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383
http://www.yeapf.com/wp/?p=441
Deprecated: ltrim(): Passing null to parameter #1 ($string) of type string is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/wp-db.php on line 3030
O título é curto… muito curto

Na realidade há um apanhado de coisas que precisam ser colocadas em ordem para poder imprimir diretamente sobre um porto serial ou paralelo desde um aplicativo ElectronJS e em especifico sobre raspberry.

No nosso caso, estamos tentando imprimir sobre uma Tanca TP-650 (Uma Epson remarcada, nada mais) Então todo mundo que alguma vez programou em Clipper, C, Pascal, Basic e precisou imprimir em um porto paralelo e/ou serial, está de parabéns por terem resistido até agora. Tudo aquilo que aprenderam lá trás na pre-história vai ser tremendamente útil e correrão com vantagem e com leveza…até com lágrimas de satisfação nos olhos.

A parte mole do lance

Bom, a primeira coisa é espetar a impressora e ver o que acontece. Lembre que estamos com um Raspberry basicão e se precisamos de alguma coisa mais, iremos fazendo. E – para os desavisados de plantão – sendo que Raspbian é filhote de Debian, o que se aplique a ele quase com certeza se aplica ao paizão.

Dizemos que esta é a parte mole porque não há necessidade de drivers já que vamos imprimir direto no porto…. sim, é uma ESC/POS, então vamos mandar código binário direto para ela.

Após espetar a impressora, rode dmesg  para ver em que pé estamos.

Resultado do comando ‘dmesg’ após conectar a impressora

A primeira coisa é definir onde a impressora está conectada. No caso ela aparece como uma ‘lp’ (line-printer) numa porta usb … na realidade é a primeira impressora de linhas conectada via usb (usblp0)

Traduzido, haverá um arquivo virtual (tudo é um arquivo em Linux) na /dev/usb chamado lp0. Ou, dito de uma só vez: /dev/usb/lp0

Imprimir nesse porto deveria ser uma coisa muito simples:

echo "Meu primeiro teste" > /dev/usb/lp0

Mas, em lugar de uma bela linha dizendo “Meu primeiro teste” na impressora temos uma mensagem de erro. Isso é porque não temos direito de acessar o porto diretamente.

stat /dev/usb/lp0

Se observamos a saída do stat o proprietário é root e o grupo é lp. Você faz parte do grupo lp? quase com certeza não. Então devemos adicionar você (no nosso caso o usuário chamado pi) ao grupo chamado lp.

sudo usermod -a -G lp pi

Agora, precisa você fazer logoff e logon para que esses direitos se tornem efetivos e só depois testar de novo fazer o echo diretamente na porta lp0

Obvio que se não é lp o grupo ou lp0 o local de sua impressora, você precisa adaptar isso tudo que estamos dizendo.

Para verificar quais os grupos ao que o usuário pi pertence, você pode fazer assim:

id pi

A lança da parte mole

A parte mole é o software, mas ela precisa de uma lança e eu precisava de um trocadilho.

No nosso aplicativo quiosque, vamos instalar uma livraria que gerencia estas impressoras ESC/POS

npm install node-thermal-printer

Isso feito, vamos testar ela tentando imprimir direto desde o javascript assim que o sistema abre. (Nada mais inútil que uma etiqueta no inicio do software mas se trata apenas de um teste e são as 17:16 e estou nisto dede as 05:00 então imagina minha jucundidade)

Ai no index.html temos a carga de um .js qualquer… por exemplo “teste.js” Ele vai conter o seguinte:

var ESC=String.fromCharCode(0x1B), 
    GS=String.fromCharCode(0x1d),
    NUL=String.fromCharCode(0x00),
    SOH=String.fromCharCode(0x01),
    STX=String.fromCharCode(0x02),
    ETX=String.fromCharCode(0x03),
    EOT=String.fromCharCode(0x04),
    BOLD_START = ESC+"E"+SOH,
    BOLD_END   = ESC+"E"+NUL,
    BLANK_LINE = ESC+"d"+SOH,
    CENTER     = ESC+"a"+SOH,
    BC_CODE39  = GS+"k"+EOT,
    CUT_PAPER  = GS+"VA"+ETX;
var command=ESC+"@"+BOLD_START+"Teste do Esteban"+BOLD_END+BLANK_LINE+"Minha Coisa!!!\n"+BC_CODE39+"606"+NUL+BLANK_LINE+"606\n"+CUT_PAPER;

var printer = require("node-thermal-printer");
printer.init({
  type: 'epson',
  characterSet: 'raw',
  interface: '/dev/usb/lp0'
});

printer.print(command);
printer.execute(function(err){
    if (err) {
      console.error("Deu crepe", err);
    } else {
     console.log("Impressão realizada");
    }
  });

Com isso feito, ele imprime uma etiqueta no inicio do programa

Mas, o bom é ver a tela de depuração do ElectronJS (leia-se chrome) para poder acompanhar, depurar, testar o que está sendo feito; então antes de soltar a versão, modificamos o main.js para abrir a tela de depuração assim:

mainWindow.webContents.openDevTools()

Isto feito, temos uma linda etiqueta como a seguir

Primeira etiqueta impressa na Tanca 650 usando ElectronJS sobre Raspberry

Obvio que está desalinhada, desajeitada e que falta um seis no número padrão de testes, mas quem está ligando para isso agora?

O que segue agora é padrão, ou seja, implementar o webService de controle, a tela de configuração e a impressão usando os botões na tela.

A ponta de lança está construída.

 

]]>
http://www.yeapf.com/wp/?feed=rss2&p=441 1 441
Usando Raspberry com ElectronJS em modo Quiosque http://www.yeapf.com/wp/?p=432 Wed, 25 Jul 2018 10:39:26 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383

Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383
http://www.yeapf.com/wp/?p=432 Deprecated: ltrim(): Passing null to parameter #1 ($string) of type string is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/wp-db.php on line 3030
Temos um Raspberry e um desafio de fazer um sistema de senhas de atendimento que rode em qualquer plataforma. Então instalamos node, um boilerplate do electron, uma interface gráfica e o YeAPF para fornecer um webservice acessível por um consumidor qualquer com uma tela tipo quiosque. Instalando as coisas. Estamos partindo do suposto que seu […]]]>

Deprecated: ltrim(): Passing null to parameter #1 ($string) of type string is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/wp-db.php on line 3030
Não é desse tipo de quiosque que estamos falando

Temos um Raspberry e um desafio de fazer um sistema de senhas de atendimento que rode em qualquer plataforma.

Então instalamos node, um boilerplate do electron, uma interface gráfica e o YeAPF para fornecer um webservice acessível por um consumidor qualquer com uma tela tipo quiosque.

Instalando as coisas.

Estamos partindo do suposto que seu raspbian está já configurado com o mínimo de recursos possíveis (leia-se: sem GUI nem nada extra)

Instalando node

Primeiro usamos ssh para entrar no Raspberry e poder instalar de lá o node assim:

cd ~/
mkdir tmp-node
cd tmp-node
wget https://nodejs.org/dist/v8.2.1/node-v8.2.1-linux-armv7l.tar.xz
tar xfv node-v8.2.1-linux-armv7l.tar.xz
cd node-v8.2.1-linux-armv7l
sudo cp -R * /usr/local/

Instalando electron

Depois usando o mesmo terminal, instalamos o ElectronJS assim:

sudo npm install -g electron --unsafe-perm=true --allow-root

Instalando a interface gráfica

Como bom filho de peixe, esta truta aqui não tem interface gráfica. Então tivemos que instalar uma interface gráfica para alguém consiga enxergar alguma coisa e não apenas imaginar.

sudo apt-get update -y
sudo apt-get install --no-install-recommends -y xserver-xorg xinit
sudo apt-get install -y xfce4 xfce4-terminal
#vamos precisar desta livraria
sudo apt install libgconf2-4

Brincando com ElectronJS

Agora podemos clonar o electron-quick-start e começar a brincar com ele (Se está em MAC, Linux, Windows é a mesma coisa).

Só que isto deve ser feito do console do próprio RaspBerry para evitar uma alma angustiada.

cd ˜/
git clone https://github.com/electron/electron-quick-start quiosque
cd quiosque
npm install
export DISPLAY=:0
npm start

Feito isso, queremos que nosso aplicativo rode em modo Quiosque (se é que essa é a melhor tradução de

Kiosk) para tanto, vamos modificar o main.js

Então na função createWindow() vamos a acrescentar a seguinte linha logo após do mainWindow.loadFile(‘index.html’)

echo "Meu primeiro teste" > /dev/usb/lp0
echo 'Meu primeiro Teste' > /dev/usb/lp0
stat /dev/usb/lp1

 

Com isso, o aplicativo deve passar a rodar em tela cheia.

 

Configurando a inicialização do dispositivo

Configurando o Raspbian para fazer login automático

Agora precisamos modificar o /etc/lightdm/lightdm.conf para que o Raspberry não pare na tela de login. Ele deve ficar assim:

[Seat:*]
pam-service=lightdm
pam-autologin-service=lightdm-autologin
autologin-user=pi
autologin-user-timeout=0
session-wrapper=/etc/X11/Xsession
greeter-session=lightdm-greeter

No meu caso o usuário é pi mesmo, por isso que está pi.

Faça um reboot para ver se está tudo ok

Caso não funcione, pode ser que precise adicionar o usuário ao auto-login assim:

groupadd -r autologin
gpasswd -a pi autologin

Rodando nosso programa no login

Vamos precisar de um pequeno programa que inicie nosso programa. Isto facilitará as coisas para monitorar o programa por exemplo, ou para rodarmos outras coisas que não são do npm.

O chamaremos quiosque.sh e o colocaremos na pasta principal do usuário pi. Ou seja, ~pi/quiosque.sh (ou /home/pi/quiosque.sh que é a mesma coisa) com o seguinte conteúdo:

#!/bin/bash

logger Iniciando Quiosque
cd ~pi/quiosque && npm start
logger Finalizando Quiosque

Com isso, toda vez que chamar-mos ~pi/quiosque.sh, ele vai indicar que entrou em funcionamento e assim que ele finalizar (normalmente ou não) também o fará.

Podemos ver isso no /var/log/messages usando o tail

Criamos um arquivo em /home/pi/Desktop/ chamado quiosque.desktop com o seguinte conteúdo:

[Desktop Entry]
Name=meu-aplicativo
Comment=Quiosque
Exec=cd ~/quiosque && npm start
TryExec=cd ~/quiosque && npm start
Type=Application

E mudamos os direitos dele para poder ser executado

chmod +x /home/pi/Desktop/quiosque.desktop

Com isso, poderemos clicar duas vezes no atalho que deve ter aparecido no Desktop.

Finalmente, fazemos com que esse arquivo desktop seja chamado toda vez que fizermos login:

cd ~/.config/autostart/
ln -s ~/Desktop/quiosque.desktop .

Com isso, ao reiniciar o raspberry, o aplicativo deve aparecer em tela cheia.

Obvio que qualquer purista vai dizer que precisamos substituir o desktop. Mas isso já é farinha de outro saco. Para desenvolvimento, teste e demonstração está muito mais do que bom

Nosso desenvolvimento seguirá neste post mostrando como acessar o hardware diretamente

]]>
432
Depurando aplicativos Cordova com o Chrome http://www.yeapf.com/wp/?p=426 Tue, 26 Jun 2018 09:19:42 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383
http://www.yeapf.com/wp/?p=426 Desde a versão 4.4 o Android permite fazer uma coisa realmente útil: depurar seu aplicativo WebView (leia-se Cordova e afins) usando o próprio Chrome.

O YeAPF desde a versão 0.8.59 inclui o adb-debug que permite acompanhar a saida do console em tempo real. Isso ajuda muito mas tem vezes que o que realmente precisamos é um passo-a-passo para entendermos como que -de fato- o código se comporta. É ai que a depuração remota entra.

Ela não funciona de fábrica, e nem poderia, já que libera todo seu aplicativo na tela de qualquer Chrome.

Para ativar este recurso, é preciso modificar o MainActivity.java. Então o primeiro passo é acha-lo

$ cd meuAplicativoCordova
meuAplicativoCordova$ find . -type f -name "MainActivity.java"
./platforms/android/app/src/main/java/br/com/inovacaosistemas/meuAplicativoCordova/MainActivity.java

Uma vez achado, precisamos modificar este arquivo.

Na seção (não sessão, isso é outra coisa) dos imports acrescente os seguintes:

import android.os.Build;
import android.util.Log;
import android.content.pm.ApplicationInfo;
import android.webkit.WebView;

Depois modifique o código do onCreate() assim:

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
            if(0 != (getApplicationInfo().flags = ApplicationInfo.FLAG_DEBUGGABLE)){
                Log.i("MeuAplicativoCordova", "Habilitando depuração Web");
                WebView.setWebContentsDebuggingEnabled(true);
            }
        }

Compile, instale e rode no seu dispositivo

meuAplicativoCordova$ cordova run android

Agora abra seu chrome e navegue no inspetor de dispositivos

chrome://inspect/#devices

Escolha seu aplicativo (pode que vc tenha vários, ou quem sabe com sorte alguém tenha esquecido ligado…rs) e depure como se fosse local.

Qual a vantagem disso tudo? Bom, por mais que webView do KitKat em diante seja Chrome, ele se comporta diferente em um dispositivo e em outro. Fora que há recursos que -mesmo emulados- se comportarão de forma muito diferente no dispositivo real (Câmera, GPS, Sensor de movimento, conectividade, etc)

Já verei de fazer um script que habilite/desabilite isso sem necessidade de tanta volta.

Por enquanto, é o que há

 

 

 

]]>
426
Atualizando o npm no Windows 8, 10 etc http://www.yeapf.com/wp/?p=399 Sat, 19 May 2018 15:21:15 +0000
Deprecated: Creation of dynamic property WP_Term::$cat_ID is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 378

Deprecated: Creation of dynamic property WP_Term::$category_count is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 379

Deprecated: Creation of dynamic property WP_Term::$category_description is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 380

Deprecated: Creation of dynamic property WP_Term::$cat_name is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 381

Deprecated: Creation of dynamic property WP_Term::$category_nicename is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 382

Deprecated: Creation of dynamic property WP_Term::$category_parent is deprecated in /home/inovacao/public_html/yeapf.com/wp/wp-includes/category.php on line 383
http://www.yeapf.com/wp/?p=399 Para os desavisados de plantão, NPM é o gestor de pacotes para javascript. Leia-se “node”

Com diz a música “Estava à toa na vida…” e ai decidi desenvolver um aplicativo em Windows.

É obvio que é mentira, em que cabeça cabe logo eu desenvolver para Windows. Todavia, como a plataforma ainda insiste em sobreviver (e o fará bastante depois do sangue novo sugado da RedHat, bash, etc) há vezes que é necessário ceder um pouco e a melhor coisa é imaginar que vc estava à toa…. porque só estando à toa mesmo.

Beleza, então, resgatei o ElectronJS e instalei no Mac que era com o micro que estava trabalhando naquele momento. Depois fiz o mesmo com o notebook que é Linux. Não é o caso de ter um projeto que não rode nessas duas plataformas.

Só que ai chegou o momento de atualizar o monstro. El OSx e em Ubuntu tinha sido fácil. Foi assim:

$ npm -g i npm

Já no frankestein, o lance passa por outros lados

A primeira coisa é abrir o PowerShell como administrador.

Depois faça assim:

C:\> npm install -g npm-windows-upgrade
C:\> npm-windows-upgrade

No meu caso me deu uma lista de versões para atualizar. Escolhi a mais recente e boa. O restante funcionou lisinho

Quando for atualizar, faça assim:

C:\> npm-windows-upgrade -p -v latest

Um outro dia conto do node com YeAPF no electronJS.

]]>
399